diff --git a/Format.md b/Format.md index a1beeed..47fd339 100644 --- a/Format.md +++ b/Format.md @@ -46,7 +46,7 @@ In more detail, the JSON format consists of a bracketed sequence of records in b * The "Event" field specifies what kind of event is being reported. This field can take on the following values: "new" for newly seen connections, "change" when the connection's identifying parameters such as port numbers of QUIC connection identifiers change, "delete" for connections deleted, "spinflip" for a flip of the QUIC spin bit in a connection, "spin" for any value of a spin bit in a QUIC connection, "measurement" for new RTT measurements, and "ecnce" for ECN-related events. In addition, the "packet" signals any other update of the counters, and "periodic" signals a periodic report made every N seconds but without a preceding event such as the reception of a packet. * The "Type" field specifies the type of a connection. This field can take on the following basic values: "UDP", "TCP", "QUIC", "DNS", "COAP", "ICMP" and "SCTP". In addition, it is possible to specify aggregate connections; these take on the following types: "HOSTS" for a host-to-host aggregate, "H2NET" for a host-to-network aggregate, "NET2NET" for a network-to-network aggregate, "H2MUL" for a host to multiple networks aggregate, NET2MUL for a network to multiple networks aggregate and "MCAST" for a multicast group aggregate. - * The "Addrs" field specifies addresses associated with the connection or aggregate. In the case of an H2MUL or NET2MUL connection, the right hand address is always zero. + * The "Addrs" field specifies addresses associated with the connection or aggregate. In the case of an H2MUL or NET2MUL connection, the right hand address is a digest of the right side networks associated with that connection, represented as an IPv4 address. * The "Session" field specifies the session identifiers associated with the connection, if any. For TCP and UDP connections these are the port numbers, for QUIC the connection IDs, for ICMP the identifier field and for SCTP the verification tags and the port numbers. * The "Ts" is the timestamp, number of microseconds since the start of January 1, 1970. Note that the number is represented as an integer, given that the 53 bits of integer precision in JSON integers is sufficient. About 20 bits are needed for the microseconds part, which leaves 43 bits for the integer seconds parts; enough until year 280892. * The "State" field is the state of the connection, either "Starting", "Up", "Closing", or "Closed". diff --git a/src/spindump_analyze_event.c b/src/spindump_analyze_event.c index f25302c..446b6c4 100644 --- a/src/spindump_analyze_event.c +++ b/src/spindump_analyze_event.c @@ -257,6 +257,21 @@ spindump_analyze_event_parseside1host(const struct spindump_event* event) { return(1); } +// +// Check that the given event side2 address/network is indeed a host +// not a network +// + +static int +spindump_analyze_event_parseside2host(const struct spindump_event* event) { + int host = spindump_network_ishost(&event->responderAddress); + if (!host) { + spindump_errorf("responder in this aggregate connection must be a host address"); + return(0); + } + return(1); +} + // // Parse the session id of an event representing an TCP/UDP/etc // connection that has two ports. @@ -596,15 +611,6 @@ spindump_analyze_processevent_new_connection(struct spindump_analyze* state, state->table); break; - case spindump_connection_aggregate_hostmultinet: - if (!spindump_analyze_event_parseside1host(event)) return; - *p_connection = - spindump_connections_newconnection_aggregate_hostmultinet(&event->initiatorAddress.address, - &when, - 0, - state->table); - break; - case spindump_connection_aggregate_networknetwork: *p_connection = spindump_connections_newconnection_aggregate_networknetwork(0, @@ -615,9 +621,21 @@ spindump_analyze_processevent_new_connection(struct spindump_analyze* state, state->table); break; + case spindump_connection_aggregate_hostmultinet: + if (!spindump_analyze_event_parsehostpair(event)) return; + *p_connection = + spindump_connections_newconnection_aggregate_hostmultinet(&event->initiatorAddress.address, + &event->responderAddress.address, + &when, + 0, + state->table); + break; + case spindump_connection_aggregate_networkmultinet: + if (!spindump_analyze_event_parseside2host(event)) return; *p_connection = spindump_connections_newconnection_aggregate_networkmultinet(&event->initiatorAddress, + &event->responderAddress.address, &when, 0, state->table); @@ -1165,6 +1183,22 @@ spindump_analyze_processevent_find_connection(struct spindump_analyze* state, state->table); break; + case spindump_connection_aggregate_hostmultinet: + if (!spindump_analyze_event_parsehostpair(event)) return(0); + connection = + spindump_connections_searchconnection_aggregate_hostmultinet(&event->initiatorAddress.address, + &event->responderAddress.address, + state->table); + break; + + case spindump_connection_aggregate_networkmultinet: + if (!spindump_analyze_event_parseside2host(event)) return(0); + connection = + spindump_connections_searchconnection_aggregate_networkmultinet(&event->initiatorAddress, + &event->responderAddress.address, + state->table); + break; + case spindump_connection_aggregate_multicastgroup: if (!spindump_analyze_event_parseside1host(event)) return(0); connection = @@ -1172,9 +1206,6 @@ spindump_analyze_processevent_find_connection(struct spindump_analyze* state, state->table); break; - case spindump_connection_aggregate_hostmultinet: - case spindump_connection_aggregate_networkmultinet: - return(0); // TBD ... not supported yet default: spindump_errorf("invalid connection type %u", event->connectionType); diff --git a/src/spindump_connections.c b/src/spindump_connections.c index 800d763..38b94c1 100644 --- a/src/spindump_connections.c +++ b/src/spindump_connections.c @@ -152,15 +152,21 @@ spindump_connections_getaddresses(struct spindump_connection* connection, *p_side2address = &connection->u.aggregatehostpair.side2peerAddress; break; case spindump_connection_aggregate_hostnetwork: - case spindump_connection_aggregate_hostmultinet: *p_side1address = &connection->u.aggregatehostnetwork.side1peerAddress; *p_side2address = 0; break; case spindump_connection_aggregate_networknetwork: - case spindump_connection_aggregate_networkmultinet: *p_side1address = 0; *p_side2address = 0; break; + case spindump_connection_aggregate_hostmultinet: + *p_side1address = &connection->u.aggregatehostmultinet.side1peerAddress; + *p_side2address = &connection->u.aggregatehostmultinet.identifier; + break; + case spindump_connection_aggregate_networkmultinet: + *p_side1address = 0; + *p_side2address = &connection->u.aggregatenetworkmultinet.identifier; + break; case spindump_connection_aggregate_multicastgroup: *p_side1address = 0; *p_side2address = &connection->u.aggregatemulticastgroup.group; @@ -230,12 +236,12 @@ spindump_connections_getnetworks(struct spindump_connection* connection, *p_side2network = connection->u.aggregatenetworknetwork.side2Network; break; case spindump_connection_aggregate_hostmultinet: - spindump_network_fromaddress(&connection->u.aggregatehostnetwork.side1peerAddress,p_side1network); - spindump_network_fromempty(AF_INET,p_side2network); + spindump_network_fromaddress(&connection->u.aggregatehostmultinet.side1peerAddress,p_side1network); + spindump_network_fromaddress(&connection->u.aggregatehostmultinet.identifier,p_side2network); break; case spindump_connection_aggregate_networkmultinet: - *p_side1network = connection->u.aggregatenetworknetwork.side1Network; - spindump_network_fromempty(AF_INET,p_side2network); + *p_side1network = connection->u.aggregatenetworkmultinet.side1Network; + spindump_network_fromaddress(&connection->u.aggregatenetworkmultinet.identifier,p_side2network); break; case spindump_connection_aggregate_multicastgroup: spindump_network_fromempty(AF_INET,p_side1network); @@ -767,7 +773,8 @@ spindump_connections_matches_aggregate_connection(int seenMatch, case spindump_connection_aggregate_hostmultinet: case spindump_connection_aggregate_networkmultinet: - return(0); // TBD ... not implemented yet + spindump_errorf("cannot do direct matching with a multinet aggregate"); + return(0); default: spindump_errorf("invalid connection type %u in spindump_connections_matches_aggregate_connection", @@ -824,7 +831,8 @@ spindump_connections_matches_aggregate_srcdst(const spindump_address* source, case spindump_connection_aggregate_hostmultinet: case spindump_connection_aggregate_networkmultinet: - return(0); // TBD ... not implemented yet + spindump_errorf("cannot do direct matching with a multinet aggregate"); + return(0); default: spindump_errorf("invalid connection type %u in spindump_connections_matches_aggregate_srcdst", aggregate->type); diff --git a/src/spindump_connections.h b/src/spindump_connections.h index 01ad0f9..913d2e1 100644 --- a/src/spindump_connections.h +++ b/src/spindump_connections.h @@ -147,11 +147,13 @@ spindump_connections_newconnection_aggregate_networknetwork(int defaultMatch, struct spindump_connectionstable* table); struct spindump_connection* spindump_connections_newconnection_aggregate_hostmultinet(const spindump_address* side1address, + const spindump_address* identifier, const struct timeval* when, int manuallyCreated, struct spindump_connectionstable* table); struct spindump_connection* spindump_connections_newconnection_aggregate_networkmultinet(const spindump_network* side1network, + const spindump_address* identifier, const struct timeval* when, int manuallyCreated, struct spindump_connectionstable* table); @@ -283,6 +285,14 @@ spindump_connections_searchconnection_aggregate_networknetwork(const spindump_ne const spindump_network* side2network, struct spindump_connectionstable* table); struct spindump_connection* +spindump_connections_searchconnection_aggregate_hostmultinet(const spindump_address* side1address, + const spindump_address* side2address, + struct spindump_connectionstable* table); +struct spindump_connection* +spindump_connections_searchconnection_aggregate_networkmultinet(const spindump_network* side1network, + const spindump_address* side2address, + struct spindump_connectionstable* table); +struct spindump_connection* spindump_connections_searchconnection_aggregate_multicastgroup(const spindump_address* address, struct spindump_connectionstable* table); unsigned long diff --git a/src/spindump_connections_new.c b/src/spindump_connections_new.c index eb868a4..3f630d6 100644 --- a/src/spindump_connections_new.c +++ b/src/spindump_connections_new.c @@ -776,6 +776,7 @@ spindump_connections_newconnection_aggregate_networknetwork(int defaultMatch, struct spindump_connection* spindump_connections_newconnection_aggregate_hostmultinet(const spindump_address* side1address, + const spindump_address* identifier, const struct timeval* when, int manuallyCreated, struct spindump_connectionstable* table) { @@ -789,6 +790,7 @@ spindump_connections_newconnection_aggregate_hostmultinet(const spindump_address connection->state = spindump_connection_state_static; connection->u.aggregatehostmultinet.side1peerAddress = *side1address; + connection->u.aggregatehostmultinet.identifier = *identifier; spindump_debugf("created a new host-multinet aggregate onnection %u", connection->id); return(connection); } @@ -800,6 +802,7 @@ spindump_connections_newconnection_aggregate_hostmultinet(const spindump_address struct spindump_connection* spindump_connections_newconnection_aggregate_networkmultinet(const spindump_network* side1network, + const spindump_address* identifier, const struct timeval* when, int manuallyCreated, struct spindump_connectionstable* table) { @@ -813,6 +816,7 @@ spindump_connections_newconnection_aggregate_networkmultinet(const spindump_netw connection->state = spindump_connection_state_static; connection->u.aggregatenetworkmultinet.side1Network = *side1network; + connection->u.aggregatenetworkmultinet.identifier = *identifier; spindump_debugf("created a new network-multinet aggregate onnection %u", connection->id); return(connection); } diff --git a/src/spindump_connections_print.c b/src/spindump_connections_print.c index 0cd3d27..1259a1e 100644 --- a/src/spindump_connections_print.c +++ b/src/spindump_connections_print.c @@ -462,9 +462,9 @@ spindump_connection_report_networknetwork(struct spindump_connection* connection FILE* file, int anonymize, struct spindump_reverse_dns* querier) { - fprintf(file," network 1: %40s\n", + fprintf(file," network 1: %40s\n", spindump_network_tostring(&connection->u.aggregatenetworknetwork.side1Network)); - fprintf(file," network 2: %40s\n", + fprintf(file," network 2: %40s\n", spindump_network_tostring(&connection->u.aggregatenetworknetwork.side2Network)); fprintf(file," aggregates: %40s\n", spindump_connections_set_listids(&connection->u.aggregatenetworknetwork.connections)); @@ -483,7 +483,10 @@ spindump_connection_report_hostmultinet(struct spindump_connection* connection, spindump_connection_address_tostring(anonymize, &connection->u.aggregatehostmultinet.side1peerAddress, querier)); - fprintf(file," network: multiple\n"); + fprintf(file," identifier: %40s\n", + spindump_connection_address_tostring(0, + &connection->u.aggregatehostmultinet.identifier, + querier)); fprintf(file," aggregates: %40s\n", spindump_connections_set_listids(&connection->u.aggregatehostmultinet.connections)); } @@ -497,9 +500,12 @@ spindump_connection_report_networkmultinet(struct spindump_connection* connectio FILE* file, int anonymize, struct spindump_reverse_dns* querier) { - fprintf(file," network 1: %40s\n", + fprintf(file," network 1: %40s\n", spindump_network_tostring(&connection->u.aggregatenetworkmultinet.side1Network)); - fprintf(file," network 2: multiple\n"); + fprintf(file," identifier: %40s\n", + spindump_connection_address_tostring(0, + &connection->u.aggregatenetworkmultinet.identifier, + querier)); fprintf(file," aggregates: %40s\n", spindump_connections_set_listids(&connection->u.aggregatenetworkmultinet.connections)); } @@ -787,12 +793,16 @@ spindump_connection_addresses(struct spindump_connection* connection, spindump_connection_address_tostring(anonymizeLeft,&connection->u.aggregatehostmultinet.side1peerAddress,querier), sizeof(buf)); spindump_strlcat(buf,middle,sizeof(buf)); - spindump_strlcat(buf,"multiple",sizeof(buf)); + spindump_strlcat(buf, + spindump_connection_address_tostring(anonymizeLeft,&connection->u.aggregatehostmultinet.identifier,querier), + sizeof(buf)); break; case spindump_connection_aggregate_networkmultinet: spindump_strlcpy(buf,spindump_network_tostring(&connection->u.aggregatenetworkmultinet.side1Network),sizeof(buf)); spindump_strlcat(buf,middle,sizeof(buf)); - spindump_strlcat(buf,"multiple",sizeof(buf)); + spindump_strlcat(buf, + spindump_connection_address_tostring(anonymizeLeft,&connection->u.aggregatenetworkmultinet.identifier,querier), + sizeof(buf)); break; case spindump_connection_aggregate_multicastgroup: spindump_strlcpy(buf,spindump_address_tostring(&connection->u.aggregatemulticastgroup.group),sizeof(buf)); diff --git a/src/spindump_connections_search.c b/src/spindump_connections_search.c index 43a5ed3..422a155 100644 --- a/src/spindump_connections_search.c +++ b/src/spindump_connections_search.c @@ -248,6 +248,25 @@ spindump_connections_match(struct spindump_connection* connection, *fromResponder = 0; fromResponderSet = 1; break; + + case spindump_connection_searchcriteria_srcdst_both_networkhost: + spindump_connections_getnetworks(connection,&side1network,&side2network); + if (!spindump_network_equal(&side1network,&criteria->side1network)) { + spindump_deepdeepdebugf("match fails because side 1 is not equal"); + return(0); + } + if (!spindump_network_ishost(&side2network)) { + spindump_deepdeepdebugf("match fails because side2 is not a host"); + return(0); + } + side2address = &side2network.address; + if (!spindump_address_equal(side2address,&criteria->side2address)) { + spindump_deepdeepdebugf("match fails because side2 is not equal"); + return(0); + } + *fromResponder = 0; + fromResponderSet = 1; + break; default: spindump_errorf("invalid match addresses criteria"); @@ -411,6 +430,7 @@ spindump_connections_match(struct spindump_connection* connection, case spindump_connection_searchcriteria_srcdst_both_hostnetwork: case spindump_connection_searchcriteria_srcdst_both_networknetwork: + case spindump_connection_searchcriteria_srcdst_both_networkhost: default: spindump_errorf("invalid match addresses criteria"); return(0); @@ -1239,6 +1259,56 @@ spindump_connections_searchconnection_aggregate_networknetwork(const spindump_ne &fromResponder)); } +struct spindump_connection* +spindump_connections_searchconnection_aggregate_hostmultinet(const spindump_address* side1address, + const spindump_address* side2address, + struct spindump_connectionstable* table) { + spindump_assert(side1address != 0); + spindump_assert(side2address != 0); + spindump_assert(table != 0); + + struct spindump_connection_searchcriteria criteria; + memset(&criteria,0,sizeof(criteria)); + + criteria.matchType = 1; + criteria.type = spindump_connection_aggregate_hostmultinet; + + criteria.matchAddresses = spindump_connection_searchcriteria_srcdst_both; + criteria.side1address = *side1address; + criteria.side2address = *side2address; + + int fromResponder; + + return(spindump_connections_search(&criteria, + table, + &fromResponder)); +} + +struct spindump_connection* +spindump_connections_searchconnection_aggregate_networkmultinet(const spindump_network* side1network, + const spindump_address* side2address, + struct spindump_connectionstable* table) { + spindump_assert(side1network != 0); + spindump_assert(side2address != 0); + spindump_assert(table != 0); + + struct spindump_connection_searchcriteria criteria; + memset(&criteria,0,sizeof(criteria)); + + criteria.matchType = 1; + criteria.type = spindump_connection_aggregate_networkmultinet; + + criteria.matchAddresses = spindump_connection_searchcriteria_srcdst_both_networkhost; + criteria.side1network = *side1network; + criteria.side2address = *side2address; + + int fromResponder; + + return(spindump_connections_search(&criteria, + table, + &fromResponder)); +} + struct spindump_connection* spindump_connections_searchconnection_aggregate_multicastgroup(const spindump_address* address, struct spindump_connectionstable* table) { diff --git a/src/spindump_connections_structs.h b/src/spindump_connections_structs.h index 4ed5b69..c342127 100644 --- a/src/spindump_connections_structs.h +++ b/src/spindump_connections_structs.h @@ -259,11 +259,13 @@ struct spindump_connection { struct { spindump_address side1peerAddress; // address of host on side 1 + spindump_address identifier; // random address used to identify the aggregate struct spindump_connection_set connections; // what actual connections fall under this aggregate } aggregatehostmultinet; struct { spindump_network side1Network; // network address on side 1 + spindump_address identifier; // random address used to identify the aggregate struct spindump_connection_set connections; // what actual connections fall under this aggregate } aggregatenetworkmultinet; @@ -283,7 +285,8 @@ enum spindump_connection_searchcriteria_srcdst { spindump_connection_searchcriteria_srcdst_both = 3, spindump_connection_searchcriteria_srcdst_both_allowreverse = 4, spindump_connection_searchcriteria_srcdst_both_hostnetwork = 5, - spindump_connection_searchcriteria_srcdst_both_networknetwork = 6 + spindump_connection_searchcriteria_srcdst_both_networknetwork = 6, + spindump_connection_searchcriteria_srcdst_both_networkhost = 7 }; struct spindump_connection_searchcriteria { diff --git a/src/spindump_main.c b/src/spindump_main.c index 55c9bd8..92de0a0 100644 --- a/src/spindump_main.c +++ b/src/spindump_main.c @@ -84,6 +84,7 @@ int main(int argc,char** argv) { FILE* debugfile = stderr; struct spindump_main_state* state = spindump_main_initialize(); interruptFlagLocation = &state->interrupt; + srand(clock()); if (state == 0) exit(1); diff --git a/src/spindump_main_lib.c b/src/spindump_main_lib.c index e9edcf9..4d47455 100644 --- a/src/spindump_main_lib.c +++ b/src/spindump_main_lib.c @@ -765,6 +765,44 @@ spindump_main_processargs(int argc, overlaps++; } } + + // + // Create an identifier for each multinet aggregate by creating a digest of the networks + // belonging to that aggregate, in sort order. Place the identifier in the side 2 address + // of the aggregate. + // + + for (unsigned int i = 0; i < config->nAggregates; i++) { + struct spindump_main_aggregate* a = &config->aggregates[i]; + if (config->aggregates[i].side2type != multinet) + continue; + uint32_t digest = spindump_crc32c_init(); + spindump_address_frombytes(&a->side2address, AF_INET, (void *)&digest); + } + for (unsigned int i = 0; i < config->nAggrnetws; i++) { + struct spindump_main_aggrnetw* anw = &config->aggrnetws[i]; + unsigned char addrbytes[16], lenbyte; + sa_family_t af; + uint32_t digest; + spindump_assert(anw->aggregate->side2type == multinet); + spindump_address_tobytes(&anw->aggregate->side2address, &af, (void *)&digest); + spindump_assert(af == AF_INET); + spindump_address_tobytes(&anw->network.address, &af, addrbytes); + lenbyte = (unsigned char)anw->network.length; + digest = spindump_crc32c_update(digest, addrbytes, af == AF_INET ? 4 : 16); + digest = spindump_crc32c_update(digest, &lenbyte, 1); + spindump_address_frombytes(&anw->aggregate->side2address, AF_INET, (void *)&digest); + } + for (unsigned int i = 0; i < config->nAggregates; i++) { + struct spindump_main_aggregate* a = &config->aggregates[i]; + if (config->aggregates[i].side2type != multinet) + continue; + uint32_t digest; + sa_family_t af; + spindump_address_tobytes(&a->side2address, &af, (void *)&digest); + digest = htonl(spindump_crc32c_finish(digest)); + spindump_address_frombytes(&a->side2address, AF_INET, (void *)&digest); + } } // diff --git a/src/spindump_main_loop.c b/src/spindump_main_loop.c index 154e63e..8068780 100644 --- a/src/spindump_main_loop.c +++ b/src/spindump_main_loop.c @@ -606,6 +606,7 @@ spindump_main_loop_initialize_aggregates(struct spindump_main_configuration* con analyzer->table); } else if (aggregate->side1ishost && aggregate->side2type == multinet) { aggregateConnection = spindump_connections_newconnection_aggregate_hostmultinet(&aggregate->side1address, + &aggregate->side2address, &startTime, 1, analyzer->table); @@ -625,6 +626,7 @@ spindump_main_loop_initialize_aggregates(struct spindump_main_configuration* con analyzer->table); } else if (!aggregate->side1ishost && aggregate->side2type == multinet) { aggregateConnection = spindump_connections_newconnection_aggregate_networkmultinet(&aggregate->side1network, + &aggregate->side2address, &startTime, 1, analyzer->table); diff --git a/src/spindump_util.c b/src/spindump_util.c index 0737400..64c5c78 100644 --- a/src/spindump_util.c +++ b/src/spindump_util.c @@ -634,6 +634,31 @@ spindump_address_frombytes(spindump_address* address, } } +// +// Write address to buffer +// + +void +spindump_address_tobytes(const spindump_address* address, + sa_family_t *af, + unsigned char* string) { + spindump_assert(address != 0); + spindump_assert(af != 0); + spindump_assert(address->ss_family == AF_INET || address->ss_family == AF_INET6); + *af = address->ss_family; + if (address->ss_family == AF_INET) { + struct sockaddr_in* actual = (struct sockaddr_in*)address; + memcpy(string, + (unsigned char*)&actual->sin_addr.s_addr, + 4); + } else { + struct sockaddr_in6* actual = (struct sockaddr_in6*)address; + memcpy(string, + (unsigned char*)&actual->sin6_addr.s6_addr, + 16); + } +} + // // Convert an address to a string. Returned string need not be freed, // but will not survive the next call to this same function. @@ -975,3 +1000,82 @@ spindump_strlcat(char * restrict dst, const char * restrict src, size_t size) { return(strlen(src)); } +// +// CRC-32c calculation. +// + +// 32 lowest bits of CRC-32c (Castagnoli93) generator polynomial. +static const uint32_t spindump_crc32c_poly = 0x1edc6f41UL; + +static uint32_t spindump_crc32c_table[256]; +static int spindump_crc32c_setup_done; + +static inline unsigned char +spindump_crc32c_bitrev8(unsigned char byte) +{ + unsigned char rev; + + rev = (byte >> 4 & 0x0f) | (byte << 4 & 0xf0); + rev = (rev >> 2 & 0x33) | (rev << 2 & 0xcc); + rev = (rev >> 1 & 0x55) | (rev << 1 & 0xaa); + return rev; +} + +static inline uint32_t +spindump_crc32c_bitrev32(uint32_t quad) +{ + uint32_t rev; + + rev = (quad >> 4 & 0x0f0f0f0f) | (quad << 4 & 0xf0f0f0f0); + rev = (rev >> 2 & 0x33333333) | (rev << 2 & 0xcccccccc); + rev = (rev >> 1 & 0x55555555) | (rev << 1 & 0xaaaaaaaa); + return rev; +} + +static void +spindump_crc32c_setup(void) +{ + uint32_t rem; + unsigned i, j; + + for (i = 0; i < 256; i++) { + rem = (uint32_t)i << 24; + for (j = 0; j < 8; j++) { + if ((rem & 0x80000000)) + rem = (rem << 1) ^ spindump_crc32c_poly; + else + rem = (rem << 1); + } + spindump_crc32c_table[spindump_crc32c_bitrev8(i)] = spindump_crc32c_bitrev32(rem); + } +} + +uint32_t +spindump_crc32c_init(void) +{ + if (!spindump_crc32c_setup_done) { + spindump_crc32c_setup_done = 1; + spindump_crc32c_setup(); + } + return 0xffffffff; +} + +uint32_t +spindump_crc32c_update(uint32_t digest, unsigned char* buf, size_t len) +{ + unsigned int i; + uint32_t newdig = digest; + unsigned char byte; + + for (i = 0; i < len; i++) { + byte = (newdig >> 24) ^ buf[i]; + newdig = (newdig << 8) ^ spindump_crc32c_table[byte]; + } + return newdig; +} + +uint32_t +spindump_crc32c_finish(uint32_t digest) +{ + return ~digest; +} diff --git a/src/spindump_util.h b/src/spindump_util.h index 1409bf6..47e8bd6 100644 --- a/src/spindump_util.h +++ b/src/spindump_util.h @@ -113,6 +113,10 @@ void spindump_address_frombytes(spindump_address* address, sa_family_t af, const unsigned char* string); +void +spindump_address_tobytes(const spindump_address* address, + sa_family_t* af, + unsigned char* string); const char* spindump_address_tostring(const spindump_address* address); const char* @@ -189,4 +193,11 @@ spindump_strlcpy(char * restrict dst, const char * restrict src, size_t size); size_t spindump_strlcat(char * restrict dst, const char * restrict src, size_t size); +uint32_t +spindump_crc32c_init(void); +uint32_t +spindump_crc32c_update(uint32_t digest, unsigned char* buf, size_t len); +uint32_t +spindump_crc32c_finish(uint32_t digest); + #endif // SPIDUMP_UTIL_H