static uint64_t hash(DnsResourceRecord *rr) { struct siphash state; siphash24_init(&state, HASH_KEY.bytes); dns_resource_record_hash_func(rr, &state); return siphash24_finalize(&state); }
static JournalRateLimitGroup* journal_rate_limit_group_new(JournalRateLimit *r, const char *id, usec_t ts) { JournalRateLimitGroup *g; struct siphash state; assert(r); assert(id); g = new0(JournalRateLimitGroup, 1); if (!g) return NULL; g->id = strdup(id); if (!g->id) goto fail; siphash24_init(&state, r->hash_key); string_hash_func(g->id, &state); g->hash = siphash24_finalize(&state); journal_rate_limit_vacuum(r, ts); LIST_PREPEND(bucket, r->buckets[g->hash % BUCKETS_MAX], g); LIST_PREPEND(lru, r->lru, g); if (!g->lru_next) r->lru_tail = g; r->n_groups++; g->parent = r; return g; fail: journal_rate_limit_group_free(g); return NULL; }
static int do_test(const uint8_t *in, size_t len, const uint8_t *key) { struct siphash state = {}; uint64_t out = 0; unsigned i, j; out = siphash24(in, len, key); assert_se(out == 0xa129ca6149be45e5); /* verify the internal state as given in the above paper */ siphash24_init(&state, key); assert_se(state.v0 == 0x7469686173716475); assert_se(state.v1 == 0x6b617f6d656e6665); assert_se(state.v2 == 0x6b7f62616d677361); assert_se(state.v3 == 0x7b6b696e727e6c7b); siphash24_compress(in, len, &state); assert_se(state.v0 == 0x4a017198de0a59e0); assert_se(state.v1 == 0x0d52f6f62a4f59a4); assert_se(state.v2 == 0x634cb3577b01fd3d); assert_se(state.v3 == 0xa5224d6f55c7d9c8); out = siphash24_finalize(&state); assert_se(out == 0xa129ca6149be45e5); assert_se(state.v0 == 0xf6bcd53893fecff1); assert_se(state.v1 == 0x54b9964c7ea0d937); assert_se(state.v2 == 0x1b38329c099bb55a); assert_se(state.v3 == 0x1814bb89ad7be679); /* verify that decomposing the input in three chunks gives the same result */ for (i = 0; i < len; i++) { for (j = i; j < len; j++) { siphash24_init(&state, key); siphash24_compress(in, i, &state); siphash24_compress(&in[i], j - i, &state); siphash24_compress(&in[j], len - j, &state); out = siphash24_finalize(&state); assert_se(out == 0xa129ca6149be45e5); } } return 0; }
static void test_message_handler(void) { _cleanup_(sd_dhcp_server_unrefp) sd_dhcp_server *server = NULL; struct { DHCPMessage message; struct { uint8_t code; uint8_t length; uint8_t type; } _packed_ option_type; struct { uint8_t code; uint8_t length; be32_t address; } _packed_ option_requested_ip; struct { uint8_t code; uint8_t length; be32_t address; } _packed_ option_server_id; struct { uint8_t code; uint8_t length; uint8_t id[7]; } _packed_ option_client_id; uint8_t end; } _packed_ test = { .message.op = BOOTREQUEST, .message.htype = ARPHRD_ETHER, .message.hlen = ETHER_ADDR_LEN, .message.xid = htobe32(0x12345678), .message.chaddr = { 'A', 'B', 'C', 'D', 'E', 'F' }, .option_type.code = SD_DHCP_OPTION_MESSAGE_TYPE, .option_type.length = 1, .option_type.type = DHCP_DISCOVER, .end = SD_DHCP_OPTION_END, }; struct in_addr address_lo = { .s_addr = htonl(INADDR_LOOPBACK), }; assert_se(sd_dhcp_server_new(&server, 1) >= 0); assert_se(sd_dhcp_server_configure_pool(server, &address_lo, 8, 0, 0) >= 0); assert_se(sd_dhcp_server_attach_event(server, NULL, 0) >= 0); assert_se(sd_dhcp_server_start(server) >= 0); assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER); test.end = 0; /* TODO, shouldn't this fail? */ assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER); test.end = SD_DHCP_OPTION_END; assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER); test.option_type.code = 0; test.option_type.length = 0; test.option_type.type = 0; assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0); test.option_type.code = SD_DHCP_OPTION_MESSAGE_TYPE; test.option_type.length = 1; test.option_type.type = DHCP_DISCOVER; assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER); test.message.op = 0; assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0); test.message.op = BOOTREQUEST; assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER); test.message.htype = 0; assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0); test.message.htype = ARPHRD_ETHER; assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER); test.message.hlen = 0; assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0); test.message.hlen = ETHER_ADDR_LEN; assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER); test.option_type.type = DHCP_REQUEST; assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0); test.option_requested_ip.code = SD_DHCP_OPTION_REQUESTED_IP_ADDRESS; test.option_requested_ip.length = 4; test.option_requested_ip.address = htobe32(0x12345678); assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_NAK); test.option_server_id.code = SD_DHCP_OPTION_SERVER_IDENTIFIER; test.option_server_id.length = 4; test.option_server_id.address = htobe32(INADDR_LOOPBACK); test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 3); assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_ACK); test.option_server_id.address = htobe32(0x12345678); test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 3); assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0); test.option_server_id.address = htobe32(INADDR_LOOPBACK); test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 4); assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0); test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 3); assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_ACK); test.option_client_id.code = SD_DHCP_OPTION_CLIENT_IDENTIFIER; test.option_client_id.length = 7; test.option_client_id.id[0] = 0x01; test.option_client_id.id[1] = 'A'; test.option_client_id.id[2] = 'B'; test.option_client_id.id[3] = 'C'; test.option_client_id.id[4] = 'D'; test.option_client_id.id[5] = 'E'; test.option_client_id.id[6] = 'F'; assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_ACK); test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 30); assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0); } static uint64_t client_id_hash_helper(DHCPClientId *id, uint8_t key[HASH_KEY_SIZE]) { struct siphash state; siphash24_init(&state, key); client_id_hash_func(id, &state); return htole64(siphash24_finalize(&state)); } static void test_client_id_hash(void) { DHCPClientId a = { .length = 4, }, b = {
int journal_rate_limit_test(JournalRateLimit *r, const char *id, int priority, uint64_t available) { uint64_t h; JournalRateLimitGroup *g; JournalRateLimitPool *p; struct siphash state; unsigned burst; usec_t ts; assert(id); /* Returns: * * 0 → the log message shall be suppressed, * 1 + n → the log message shall be permitted, and n messages were dropped from the peer before * < 0 → error */ if (!r) return 1; if (r->interval == 0 || r->burst == 0) return 1; burst = burst_modulate(r->burst, available); ts = now(CLOCK_MONOTONIC); siphash24_init(&state, r->hash_key); string_hash_func(id, &state); h = siphash24_finalize(&state); g = r->buckets[h % BUCKETS_MAX]; LIST_FOREACH(bucket, g, g) if (streq(g->id, id)) break; if (!g) { g = journal_rate_limit_group_new(r, id, ts); if (!g) return -ENOMEM; } p = &g->pools[priority_map[priority]]; if (p->begin <= 0) { p->suppressed = 0; p->num = 1; p->begin = ts; return 1; } if (p->begin + r->interval < ts) { unsigned s; s = p->suppressed; p->suppressed = 0; p->num = 1; p->begin = ts; return 1 + s; } if (p->num < burst) { p->num++; return 1; } p->suppressed++; return 0; }