diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/activate/activate.c | 2 | ||||
-rw-r--r-- | src/basic/strbuf.c | 4 | ||||
-rw-r--r-- | src/basic/time-util.c | 37 | ||||
-rw-r--r-- | src/journal/catalog.c | 81 | ||||
-rw-r--r-- | src/journal/test-catalog.c | 2 | ||||
-rw-r--r-- | src/resolve/resolve-tool.c | 97 | ||||
-rw-r--r-- | src/resolve/resolved-dns-rr.c | 33 | ||||
-rw-r--r-- | src/test/test-hashmap-plain.c | 15 |
8 files changed, 184 insertions, 87 deletions
diff --git a/src/activate/activate.c b/src/activate/activate.c index 23244fdc62..d6e2d07ff2 100644 --- a/src/activate/activate.c +++ b/src/activate/activate.c @@ -385,7 +385,7 @@ static int parse_argv(int argc, char *argv[]) { assert(argc >= 0); assert(argv); - while ((c = getopt_long(argc, argv, "+hl:aEd", options, NULL)) >= 0) + while ((c = getopt_long(argc, argv, "+hl:aE:d", options, NULL)) >= 0) switch(c) { case 'h': help(); diff --git a/src/basic/strbuf.c b/src/basic/strbuf.c index 77220c0251..dac2881603 100644 --- a/src/basic/strbuf.c +++ b/src/basic/strbuf.c @@ -156,6 +156,10 @@ ssize_t strbuf_add_string(struct strbuf *str, const char *s, size_t len) { return off; } + /* bsearch is not allowed on a NULL sequence */ + if (node->children_count == 0) + break; + /* lookup child node */ c = s[len - 1 - depth]; search.c = c; diff --git a/src/basic/time-util.c b/src/basic/time-util.c index 0b4f5ab5b9..130acaa9de 100644 --- a/src/basic/time-util.c +++ b/src/basic/time-util.c @@ -705,8 +705,7 @@ finish: return 0; } -int parse_time(const char *t, usec_t *usec, usec_t default_unit) { - +static char* extract_multiplier(char *p, usec_t *multiplier) { static const struct { const char *suffix; usec_t usec; @@ -740,7 +739,22 @@ int parse_time(const char *t, usec_t *usec, usec_t default_unit) { { "usec", 1ULL }, { "us", 1ULL }, }; + unsigned i; + + for (i = 0; i < ELEMENTSOF(table); i++) { + char *e; + e = startswith(p, table[i].suffix); + if (e) { + *multiplier = table[i].usec; + return e; + } + } + + return p; +} + +int parse_time(const char *t, usec_t *usec, usec_t default_unit) { const char *p, *s; usec_t r = 0; bool something = false; @@ -765,8 +779,8 @@ int parse_time(const char *t, usec_t *usec, usec_t default_unit) { for (;;) { long long l, z = 0; char *e; - unsigned i, n = 0; - usec_t multiplier, k; + unsigned n = 0; + usec_t multiplier = default_unit, k; p += strspn(p, WHITESPACE); @@ -779,10 +793,8 @@ int parse_time(const char *t, usec_t *usec, usec_t default_unit) { errno = 0; l = strtoll(p, &e, 10); - if (errno > 0) return -errno; - if (l < 0) return -ERANGE; @@ -806,18 +818,7 @@ int parse_time(const char *t, usec_t *usec, usec_t default_unit) { return -EINVAL; e += strspn(e, WHITESPACE); - - for (i = 0; i < ELEMENTSOF(table); i++) - if (startswith(e, table[i].suffix)) { - multiplier = table[i].usec; - p = e + strlen(table[i].suffix); - break; - } - - if (i >= ELEMENTSOF(table)) { - multiplier = default_unit; - p = e; - } + p = extract_multiplier(e, &multiplier); something = true; diff --git a/src/journal/catalog.c b/src/journal/catalog.c index 164a3a15f2..72c2da10f1 100644 --- a/src/journal/catalog.c +++ b/src/journal/catalog.c @@ -164,14 +164,14 @@ static int finish_item( Hashmap *h, sd_id128_t id, const char *language, - char *payload) { + char *payload, size_t payload_size) { _cleanup_free_ CatalogItem *i = NULL; - _cleanup_free_ char *combined = NULL, *prev = NULL; - int r; + _cleanup_free_ char *prev = NULL, *combined = NULL; assert(h); assert(payload); + assert(payload_size > 0); i = new0(CatalogItem, 1); if (!i) @@ -184,23 +184,25 @@ static int finish_item( } prev = hashmap_get(h, i); - - /* Already have such an item, combine them */ if (prev) { + /* Already have such an item, combine them */ combined = combine_entries(payload, prev); if (!combined) return log_oom(); - r = hashmap_update(h, i, combined); - if (r < 0) - return r; - combined = NULL; - /* A new item */ + if (hashmap_update(h, i, combined) < 0) + return log_oom(); + combined = NULL; } else { - r = hashmap_put(h, i, payload); - if (r < 0) - return r; + /* A new item */ + combined = memdup(payload, payload_size + 1); + if (!combined) + return log_oom(); + + if (hashmap_put(h, i, combined) < 0) + return log_oom(); i = NULL; + combined = NULL; } return 0; @@ -262,6 +264,7 @@ static int catalog_entry_lang(const char* filename, int line, int catalog_import_file(Hashmap *h, const char *path) { _cleanup_fclose_ FILE *f = NULL; _cleanup_free_ char *payload = NULL; + size_t payload_size = 0, payload_allocated = 0; unsigned n = 0; sd_id128_t id; _cleanup_free_ char *deflang = NULL, *lang = NULL; @@ -283,8 +286,7 @@ int catalog_import_file(Hashmap *h, const char *path) { for (;;) { char line[LINE_MAX]; - size_t a, b, c; - char *t; + size_t line_len; if (!fgets(line, sizeof(line), f)) { if (feof(f)) @@ -323,17 +325,23 @@ int catalog_import_file(Hashmap *h, const char *path) { if (sd_id128_from_string(line + 2 + 1, &jd) >= 0) { if (got_id) { - r = finish_item(h, id, lang ?: deflang, payload); + if (payload_size == 0) { + log_error("[%s:%u] No payload text.", path, n); + return -EINVAL; + } + + r = finish_item(h, id, lang ?: deflang, payload, payload_size); if (r < 0) return r; - payload = NULL; lang = mfree(lang); + payload_size = 0; } if (with_language) { - t = strstrip(line + 2 + 1 + 32 + 1); + char *t; + t = strstrip(line + 2 + 1 + 32 + 1); r = catalog_entry_lang(path, n, t, deflang, &lang); if (r < 0) return r; @@ -343,9 +351,6 @@ int catalog_import_file(Hashmap *h, const char *path) { empty_line = false; id = jd; - if (payload) - payload[0] = '\0'; - continue; } } @@ -356,34 +361,30 @@ int catalog_import_file(Hashmap *h, const char *path) { return -EINVAL; } - a = payload ? strlen(payload) : 0; - b = strlen(line); - - c = a + (empty_line ? 1 : 0) + b + 1 + 1; - t = realloc(payload, c); - if (!t) + line_len = strlen(line); + if (!GREEDY_REALLOC(payload, payload_allocated, + payload_size + (empty_line ? 1 : 0) + line_len + 1 + 1)) return log_oom(); - if (empty_line) { - t[a] = '\n'; - memcpy(t + a + 1, line, b); - t[a+b+1] = '\n'; - t[a+b+2] = 0; - } else { - memcpy(t + a, line, b); - t[a+b] = '\n'; - t[a+b+1] = 0; - } + if (empty_line) + payload[payload_size++] = '\n'; + memcpy(payload + payload_size, line, line_len); + payload_size += line_len; + payload[payload_size++] = '\n'; + payload[payload_size] = '\0'; - payload = t; empty_line = false; } if (got_id) { - r = finish_item(h, id, lang ?: deflang, payload); + if (payload_size == 0) { + log_error("[%s:%u] No payload text.", path, n); + return -EINVAL; + } + + r = finish_item(h, id, lang ?: deflang, payload, payload_size); if (r < 0) return r; - payload = NULL; } return 0; diff --git a/src/journal/test-catalog.c b/src/journal/test-catalog.c index da6fcbca4d..898c876450 100644 --- a/src/journal/test-catalog.c +++ b/src/journal/test-catalog.c @@ -103,6 +103,8 @@ static void test_catalog_import_one(void) { assert_se(hashmap_size(h) == 1); HASHMAP_FOREACH(payload, h, j) { + printf("expect: %s\n", expect); + printf("actual: %s\n", payload); assert_se(streq(expect, payload)); } } diff --git a/src/resolve/resolve-tool.c b/src/resolve/resolve-tool.c index a519074278..484fbb4d92 100644 --- a/src/resolve/resolve-tool.c +++ b/src/resolve/resolve-tool.c @@ -44,12 +44,19 @@ static uint16_t arg_class = 0; static bool arg_legend = true; static uint64_t arg_flags = 0; +typedef enum ServiceFamily { + SERVICE_FAMILY_TCP, + SERVICE_FAMILY_UDP, + SERVICE_FAMILY_SCTP, + _SERVICE_FAMILY_INVALID = -1, +} ServiceFamily; +static ServiceFamily arg_service_family = SERVICE_FAMILY_TCP; + typedef enum RawType { RAW_NONE, RAW_PAYLOAD, RAW_PACKET, } RawType; - static RawType arg_raw = RAW_NONE; static enum { @@ -57,10 +64,34 @@ static enum { MODE_RESOLVE_RECORD, MODE_RESOLVE_SERVICE, MODE_RESOLVE_OPENPGP, + MODE_RESOLVE_TLSA, MODE_STATISTICS, MODE_RESET_STATISTICS, } arg_mode = MODE_RESOLVE_HOST; +static ServiceFamily service_family_from_string(const char *s) { + if (s == NULL || streq(s, "tcp")) + return SERVICE_FAMILY_TCP; + if (streq(s, "udp")) + return SERVICE_FAMILY_UDP; + if (streq(s, "sctp")) + return SERVICE_FAMILY_SCTP; + return _SERVICE_FAMILY_INVALID; +} + +static const char* service_family_to_string(ServiceFamily service) { + switch(service) { + case SERVICE_FAMILY_TCP: + return "_tcp"; + case SERVICE_FAMILY_UDP: + return "_udp"; + case SERVICE_FAMILY_SCTP: + return "_sctp"; + default: + assert_not_reached("invalid service"); + } +} + static void print_source(uint64_t flags, usec_t rtt) { char rtt_str[FORMAT_TIMESTAMP_MAX]; @@ -844,6 +875,38 @@ static int resolve_openpgp(sd_bus *bus, const char *address) { arg_type ?: DNS_TYPE_OPENPGPKEY); } +static int resolve_tlsa(sd_bus *bus, const char *address) { + const char *port; + uint16_t port_num = 443; + _cleanup_free_ char *full = NULL; + int r; + + assert(bus); + assert(address); + + port = strrchr(address, ':'); + if (port) { + r = safe_atou16(port + 1, &port_num); + if (r < 0 || port_num == 0) + return log_error_errno(r, "Invalid port \"%s\".", port + 1); + + address = strndupa(address, port - address); + } + + r = asprintf(&full, "_%u.%s.%s", + port_num, + service_family_to_string(arg_service_family), + address); + if (r < 0) + return log_oom(); + + log_debug("Looking up \"%s\".", full); + + return resolve_record(bus, full, + arg_class ?: DNS_CLASS_IN, + arg_type ?: DNS_TYPE_TLSA); +} + static int show_statistics(sd_bus *bus) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; @@ -1031,6 +1094,7 @@ static void help(void) { " --service-address=BOOL Resolve address for services (default: yes)\n" " --service-txt=BOOL Resolve TXT records for services (default: yes)\n" " --openpgp Query OpenPGP public key\n" + " --tlsa Query TLS public key\n" " --cname=BOOL Follow CNAME redirects (default: yes)\n" " --search=BOOL Use search domains for single-label names\n" " (default: yes)\n" @@ -1050,6 +1114,7 @@ static int parse_argv(int argc, char *argv[]) { ARG_SERVICE_ADDRESS, ARG_SERVICE_TXT, ARG_OPENPGP, + ARG_TLSA, ARG_RAW, ARG_SEARCH, ARG_STATISTICS, @@ -1069,6 +1134,7 @@ static int parse_argv(int argc, char *argv[]) { { "service-address", required_argument, NULL, ARG_SERVICE_ADDRESS }, { "service-txt", required_argument, NULL, ARG_SERVICE_TXT }, { "openpgp", no_argument, NULL, ARG_OPENPGP }, + { "tlsa", optional_argument, NULL, ARG_TLSA }, { "raw", optional_argument, NULL, ARG_RAW }, { "search", required_argument, NULL, ARG_SEARCH }, { "statistics", no_argument, NULL, ARG_STATISTICS, }, @@ -1183,6 +1249,15 @@ static int parse_argv(int argc, char *argv[]) { arg_mode = MODE_RESOLVE_OPENPGP; break; + case ARG_TLSA: + arg_mode = MODE_RESOLVE_TLSA; + arg_service_family = service_family_from_string(optarg); + if (arg_service_family < 0) { + log_error("Unknown service family \"%s\".", optarg); + return -EINVAL; + } + break; + case ARG_RAW: if (on_tty()) { log_error("Refusing to write binary data to tty."); @@ -1261,7 +1336,7 @@ static int parse_argv(int argc, char *argv[]) { return -EINVAL; } - if (arg_type != 0 && arg_mode != MODE_RESOLVE_RECORD) { + if (arg_type != 0 && arg_mode == MODE_RESOLVE_SERVICE) { log_error("--service and --type= may not be combined."); return -EINVAL; } @@ -1378,6 +1453,24 @@ int main(int argc, char **argv) { } break; + case MODE_RESOLVE_TLSA: + if (argc < optind + 1) { + log_error("Domain name required."); + r = -EINVAL; + goto finish; + + } + + r = 0; + while (optind < argc) { + int k; + + k = resolve_tlsa(bus, argv[optind++]); + if (k < 0) + r = k; + } + break; + case MODE_STATISTICS: if (argc > optind) { log_error("Too many arguments."); diff --git a/src/resolve/resolved-dns-rr.c b/src/resolve/resolved-dns-rr.c index d0a86ef206..6a29a93a26 100644 --- a/src/resolve/resolved-dns-rr.c +++ b/src/resolve/resolved-dns-rr.c @@ -1116,40 +1116,30 @@ const char *dns_resource_record_to_string(DnsResourceRecord *rr) { case DNS_TYPE_TLSA: { const char *cert_usage, *selector, *matching_type; - char *ss; - int n; cert_usage = tlsa_cert_usage_to_string(rr->tlsa.cert_usage); selector = tlsa_selector_to_string(rr->tlsa.selector); matching_type = tlsa_matching_type_to_string(rr->tlsa.matching_type); - r = asprintf(&s, "%s %u %u %u %n", - k, - rr->tlsa.cert_usage, - rr->tlsa.selector, - rr->tlsa.matching_type, - &n); - if (r < 0) - return NULL; - - r = base64_append(&s, n, - rr->tlsa.data, rr->tlsa.data_size, - 8, columns()); - if (r < 0) + t = hexmem(rr->sshfp.fingerprint, rr->sshfp.fingerprint_size); + if (!t) return NULL; - r = asprintf(&ss, "%s\n" + r = asprintf(&s, + "%s %u %u %u %s\n" " -- Cert. usage: %s\n" " -- Selector: %s\n" " -- Matching type: %s", - s, + k, + rr->tlsa.cert_usage, + rr->tlsa.selector, + rr->tlsa.matching_type, + t, cert_usage, selector, matching_type); if (r < 0) return NULL; - free(s); - s = ss; break; } @@ -1228,13 +1218,16 @@ ssize_t dns_resource_record_payload(DnsResourceRecord *rr, void **out) { case DNS_TYPE_MX: case DNS_TYPE_LOC: case DNS_TYPE_DS: - case DNS_TYPE_SSHFP: case DNS_TYPE_DNSKEY: case DNS_TYPE_RRSIG: case DNS_TYPE_NSEC: case DNS_TYPE_NSEC3: return -EINVAL; + case DNS_TYPE_SSHFP: + *out = rr->sshfp.fingerprint; + return rr->sshfp.fingerprint_size; + case DNS_TYPE_TLSA: *out = rr->tlsa.data; return rr->tlsa.data_size; diff --git a/src/test/test-hashmap-plain.c b/src/test/test-hashmap-plain.c index 6bf33306a9..1bd5c02f87 100644 --- a/src/test/test-hashmap-plain.c +++ b/src/test/test-hashmap-plain.c @@ -323,26 +323,29 @@ static void test_hashmap_remove_value(void) { _cleanup_hashmap_free_ Hashmap *m = NULL; char *r; - r = hashmap_remove_value(NULL, "key 1", (void*) "val 1"); + char val1[] = "val 1"; + char val2[] = "val 2"; + + r = hashmap_remove_value(NULL, "key 1", val1); assert_se(r == NULL); m = hashmap_new(&string_hash_ops); assert_se(m); - r = hashmap_remove_value(m, "key 1", (void*) "val 1"); + r = hashmap_remove_value(m, "key 1", val1); assert_se(r == NULL); - hashmap_put(m, "key 1", (void*) "val 1"); - hashmap_put(m, "key 2", (void*) "val 2"); + hashmap_put(m, "key 1", val1); + hashmap_put(m, "key 2", val2); - r = hashmap_remove_value(m, "key 1", (void*) "val 1"); + r = hashmap_remove_value(m, "key 1", val1); assert_se(streq(r, "val 1")); r = hashmap_get(m, "key 2"); assert_se(streq(r, "val 2")); assert_se(!hashmap_get(m, "key 1")); - r = hashmap_remove_value(m, "key 2", (void*) "val 1"); + r = hashmap_remove_value(m, "key 2", val1); assert_se(r == NULL); r = hashmap_get(m, "key 2"); |