Example #1
0
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);
        }
}
Example #2
0
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);
}
Example #3
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;
}