static void test_packet_from_file(const char* filename, bool canonical) { _cleanup_free_ char *data = NULL; size_t data_size, packet_size, offset; assert_se(read_full_file(filename, &data, &data_size) >= 0); assert_se(data); assert_se(data_size > 8); log_info("============== %s %s==============", filename, canonical ? "canonical " : ""); for (offset = 0; offset < data_size; offset += 8 + packet_size) { _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL, *p2 = NULL; _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL, *rr2 = NULL; const char *s, *s2; uint64_t hash1, hash2; packet_size = unaligned_read_le64(data + offset); assert_se(packet_size > 0); assert_se(offset + 8 + packet_size <= data_size); assert_se(dns_packet_new(&p, DNS_PROTOCOL_DNS, 0) >= 0); assert_se(dns_packet_append_blob(p, data + offset + 8, packet_size, NULL) >= 0); assert_se(dns_packet_read_rr(p, &rr, NULL, NULL) >= 0); s = dns_resource_record_to_string(rr); assert_se(s); puts(s); hash1 = hash(rr); assert_se(dns_resource_record_to_wire_format(rr, canonical) >= 0); assert_se(dns_packet_new(&p2, DNS_PROTOCOL_DNS, 0) >= 0); assert_se(dns_packet_append_blob(p2, rr->wire_format, rr->wire_format_size, NULL) >= 0); assert_se(dns_packet_read_rr(p2, &rr2, NULL, NULL) >= 0); s2 = dns_resource_record_to_string(rr); assert_se(s2); assert_se(streq(s, s2)); hash2 = hash(rr); assert_se(hash1 == hash2); } }
static void test_le(void) { uint8_t scratch[16]; assert_se(unaligned_read_le16(&data[0]) == 0x0100); assert_se(unaligned_read_le16(&data[1]) == 0x0201); assert_se(unaligned_read_le32(&data[0]) == 0x03020100); assert_se(unaligned_read_le32(&data[1]) == 0x04030201); assert_se(unaligned_read_le32(&data[2]) == 0x05040302); assert_se(unaligned_read_le32(&data[3]) == 0x06050403); assert_se(unaligned_read_le64(&data[0]) == 0x0706050403020100); assert_se(unaligned_read_le64(&data[1]) == 0x0807060504030201); assert_se(unaligned_read_le64(&data[2]) == 0x0908070605040302); assert_se(unaligned_read_le64(&data[3]) == 0x0a09080706050403); assert_se(unaligned_read_le64(&data[4]) == 0x0b0a090807060504); assert_se(unaligned_read_le64(&data[5]) == 0x0c0b0a0908070605); assert_se(unaligned_read_le64(&data[6]) == 0x0d0c0b0a09080706); assert_se(unaligned_read_le64(&data[7]) == 0x0e0d0c0b0a090807); zero(scratch); unaligned_write_le16(&scratch[0], 0x0100); assert_se(memcmp(&scratch[0], &data[0], sizeof(uint16_t)) == 0); zero(scratch); unaligned_write_le16(&scratch[1], 0x0201); assert_se(memcmp(&scratch[1], &data[1], sizeof(uint16_t)) == 0); zero(scratch); unaligned_write_le32(&scratch[0], 0x03020100); assert_se(memcmp(&scratch[0], &data[0], sizeof(uint32_t)) == 0); zero(scratch); unaligned_write_le32(&scratch[1], 0x04030201); assert_se(memcmp(&scratch[1], &data[1], sizeof(uint32_t)) == 0); zero(scratch); unaligned_write_le32(&scratch[2], 0x05040302); assert_se(memcmp(&scratch[2], &data[2], sizeof(uint32_t)) == 0); zero(scratch); unaligned_write_le32(&scratch[3], 0x06050403); assert_se(memcmp(&scratch[3], &data[3], sizeof(uint32_t)) == 0); zero(scratch); unaligned_write_le64(&scratch[0], 0x0706050403020100); assert_se(memcmp(&scratch[0], &data[0], sizeof(uint64_t)) == 0); zero(scratch); unaligned_write_le64(&scratch[1], 0x0807060504030201); assert_se(memcmp(&scratch[1], &data[1], sizeof(uint64_t)) == 0); zero(scratch); unaligned_write_le64(&scratch[2], 0x0908070605040302); assert_se(memcmp(&scratch[2], &data[2], sizeof(uint64_t)) == 0); zero(scratch); unaligned_write_le64(&scratch[3], 0x0a09080706050403); assert_se(memcmp(&scratch[3], &data[3], sizeof(uint64_t)) == 0); zero(scratch); unaligned_write_le64(&scratch[4], 0x0B0A090807060504); assert_se(memcmp(&scratch[4], &data[4], sizeof(uint64_t)) == 0); zero(scratch); unaligned_write_le64(&scratch[5], 0x0c0b0a0908070605); assert_se(memcmp(&scratch[5], &data[5], sizeof(uint64_t)) == 0); zero(scratch); unaligned_write_le64(&scratch[6], 0x0d0c0b0a09080706); assert_se(memcmp(&scratch[6], &data[6], sizeof(uint64_t)) == 0); zero(scratch); unaligned_write_le64(&scratch[7], 0x0e0d0c0b0a090807); assert_se(memcmp(&scratch[7], &data[7], sizeof(uint64_t)) == 0); }
static int server_process_entry( Server *s, const void *buffer, size_t *remaining, ClientContext *context, const struct ucred *ucred, const struct timeval *tv, const char *label, size_t label_len) { /* Process a single entry from a native message. * Returns 0 if nothing special happened and the message processing should continue, * and a negative or positive value otherwise. * * Note that *remaining is altered on both success and failure. */ struct iovec *iovec = NULL; unsigned n = 0, j, tn = (unsigned) -1; const char *p; size_t m = 0, entry_size = 0; int priority = LOG_INFO; char *identifier = NULL, *message = NULL; pid_t object_pid = 0; int r = 0; p = buffer; while (*remaining > 0) { const char *e, *q; e = memchr(p, '\n', *remaining); if (!e) { /* Trailing noise, let's ignore it, and flush what we collected */ log_debug("Received message with trailing noise, ignoring."); r = 1; /* finish processing of the message */ break; } if (e == p) { /* Entry separator */ *remaining -= 1; break; } if (*p == '.' || *p == '#') { /* Ignore control commands for now, and * comments too. */ *remaining -= (e - p) + 1; p = e + 1; continue; } /* A property follows */ /* n existing properties, 1 new, +1 for _TRANSPORT */ if (!GREEDY_REALLOC(iovec, m, n + 2 + N_IOVEC_META_FIELDS + N_IOVEC_OBJECT_FIELDS)) { r = log_oom(); break; } q = memchr(p, '=', e - p); if (q) { if (valid_user_field(p, q - p, false)) { size_t l; l = e - p; /* If the field name starts with an * underscore, skip the variable, * since that indicates a trusted * field */ iovec[n].iov_base = (char*) p; iovec[n].iov_len = l; entry_size += l; n++; server_process_entry_meta(p, l, ucred, &priority, &identifier, &message, &object_pid); } *remaining -= (e - p) + 1; p = e + 1; continue; } else { uint64_t l; char *k; if (*remaining < e - p + 1 + sizeof(uint64_t) + 1) { log_debug("Failed to parse message, ignoring."); break; } l = unaligned_read_le64(e + 1); if (l > DATA_SIZE_MAX) { log_debug("Received binary data block of %"PRIu64" bytes is too large, ignoring.", l); break; } if ((uint64_t) *remaining < e - p + 1 + sizeof(uint64_t) + l + 1 || e[1+sizeof(uint64_t)+l] != '\n') { log_debug("Failed to parse message, ignoring."); break; } k = malloc((e - p) + 1 + l); if (!k) { log_oom(); break; } memcpy(k, p, e - p); k[e - p] = '='; memcpy(k + (e - p) + 1, e + 1 + sizeof(uint64_t), l); if (valid_user_field(p, e - p, false)) { iovec[n].iov_base = k; iovec[n].iov_len = (e - p) + 1 + l; entry_size += iovec[n].iov_len; n++; server_process_entry_meta(k, (e - p) + 1 + l, ucred, &priority, &identifier, &message, &object_pid); } else free(k); *remaining -= (e - p) + 1 + sizeof(uint64_t) + l + 1; p = e + 1 + sizeof(uint64_t) + l + 1; } } if (n <= 0) { r = 1; goto finish; } tn = n++; IOVEC_SET_STRING(iovec[tn], "_TRANSPORT=journal"); entry_size += strlen("_TRANSPORT=journal"); if (entry_size + n + 1 > ENTRY_SIZE_MAX) { /* data + separators + trailer */ log_debug("Entry is too big with %u properties and %zu bytes, ignoring.", n, entry_size); goto finish; } if (message) { if (s->forward_to_syslog) server_forward_syslog(s, syslog_fixup_facility(priority), identifier, message, ucred, tv); if (s->forward_to_kmsg) server_forward_kmsg(s, priority, identifier, message, ucred); if (s->forward_to_console) server_forward_console(s, priority, identifier, message, ucred); if (s->forward_to_wall) server_forward_wall(s, priority, identifier, message, ucred); } server_dispatch_message(s, iovec, n, m, context, tv, priority, object_pid); finish: for (j = 0; j < n; j++) { if (j == tn) continue; if (iovec[j].iov_base < buffer || (const char*) iovec[j].iov_base >= p + *remaining) free(iovec[j].iov_base); } free(iovec); free(identifier); free(message); return r; }