diff options
Diffstat (limited to 'src/shared')
-rw-r--r-- | src/shared/bus-util.h | 11 | ||||
-rw-r--r-- | src/shared/dns-domain.c | 95 | ||||
-rw-r--r-- | src/shared/dns-domain.h | 2 | ||||
-rw-r--r-- | src/shared/efivars.c | 14 | ||||
-rw-r--r-- | src/shared/nss-util.h | 33 | ||||
-rw-r--r-- | src/shared/sysctl-util.c | 2 |
6 files changed, 140 insertions, 17 deletions
diff --git a/src/shared/bus-util.h b/src/shared/bus-util.h index d8dba584d6..4ae216b7d9 100644 --- a/src/shared/bus-util.h +++ b/src/shared/bus-util.h @@ -135,22 +135,15 @@ typedef struct UnitInfo { int bus_parse_unit_info(sd_bus_message *message, UnitInfo *u); -static inline void sd_bus_close_unrefp(sd_bus **bus) { - if (*bus) { - sd_bus_flush(*bus); - sd_bus_close(*bus); - sd_bus_unref(*bus); - } -} - DEFINE_TRIVIAL_CLEANUP_FUNC(sd_bus*, sd_bus_unref); +DEFINE_TRIVIAL_CLEANUP_FUNC(sd_bus*, sd_bus_flush_close_unref); DEFINE_TRIVIAL_CLEANUP_FUNC(sd_bus_slot*, sd_bus_slot_unref); DEFINE_TRIVIAL_CLEANUP_FUNC(sd_bus_message*, sd_bus_message_unref); DEFINE_TRIVIAL_CLEANUP_FUNC(sd_bus_creds*, sd_bus_creds_unref); DEFINE_TRIVIAL_CLEANUP_FUNC(sd_bus_track*, sd_bus_track_unref); #define _cleanup_bus_unref_ _cleanup_(sd_bus_unrefp) -#define _cleanup_bus_close_unref_ _cleanup_(sd_bus_close_unrefp) +#define _cleanup_bus_flush_close_unref_ _cleanup_(sd_bus_flush_close_unrefp) #define _cleanup_bus_slot_unref_ _cleanup_(sd_bus_slot_unrefp) #define _cleanup_bus_message_unref_ _cleanup_(sd_bus_message_unrefp) #define _cleanup_bus_creds_unref_ _cleanup_(sd_bus_creds_unrefp) diff --git a/src/shared/dns-domain.c b/src/shared/dns-domain.c index 20a44ce4e1..8a0dec1540 100644 --- a/src/shared/dns-domain.c +++ b/src/shared/dns-domain.c @@ -114,6 +114,68 @@ int dns_label_unescape(const char **name, char *dest, size_t sz) { return r; } +/* @label_terminal: terminal character of a label, updated to point to the terminal character of + * the previous label (always skipping one dot) or to NULL if there are no more + * labels. */ +int dns_label_unescape_suffix(const char *name, const char **label_terminal, char *dest, size_t sz) { + const char *terminal; + int r; + + assert(name); + assert(label_terminal); + assert(dest); + + /* no more labels */ + if (!*label_terminal) { + if (sz >= 1) + *dest = 0; + + return 0; + } + + assert(**label_terminal == '.' || **label_terminal == 0); + + /* skip current terminal character */ + terminal = *label_terminal - 1; + + /* point name to the last label, and terminal to the preceding terminal symbol (or make it a NULL pointer) */ + for (;;) { + if (terminal < name) { + /* reached the first label, so indicate that there are no more */ + terminal = NULL; + break; + } + + /* find the start of the last label */ + if (*terminal == '.') { + const char *y; + unsigned slashes = 0; + + for (y = terminal - 1; y >= name && *y == '\\'; y--) + slashes ++; + + if (slashes % 2 == 0) { + /* the '.' was not escaped */ + name = terminal + 1; + break; + } else { + terminal = y; + continue; + } + } + + terminal --; + } + + r = dns_label_unescape(&name, dest, sz); + if (r < 0) + return r; + + *label_terminal = terminal; + + return r; +} + int dns_label_escape(const char *p, size_t l, char **ret) { _cleanup_free_ char *s = NULL; char *q; @@ -338,20 +400,23 @@ unsigned long dns_name_hash_func(const void *s, const uint8_t hash_key[HASH_KEY_ } int dns_name_compare_func(const void *a, const void *b) { - const char *x = a, *y = b; + const char *x, *y; int r, q, k, w; assert(a); assert(b); + x = (const char *) a + strlen(a); + y = (const char *) b + strlen(b); + for (;;) { char la[DNS_LABEL_MAX+1], lb[DNS_LABEL_MAX+1]; - if (*x == 0 && *y == 0) + if (x == NULL && y == NULL) return 0; - r = dns_label_unescape(&x, la, sizeof(la)); - q = dns_label_unescape(&y, lb, sizeof(lb)); + r = dns_label_unescape_suffix(a, &x, la, sizeof(la)); + q = dns_label_unescape_suffix(b, &y, lb, sizeof(lb)); if (r < 0 || q < 0) return r - q; @@ -464,6 +529,28 @@ int dns_name_endswith(const char *name, const char *suffix) { } } +int dns_name_between(const char *a, const char *b, const char *c) { + int n; + + /* Determine if b is strictly greater than a and strictly smaller than c. + We consider the order of names to be circular, so that if a is + strictly greater than c, we consider b to be between them if it is + either greater than a or smaller than c. This is how the canonical + DNS name order used in NSEC records work. */ + + n = dns_name_compare_func(a, c); + if (n == 0) + return -EINVAL; + else if (n < 0) + /* a<---b--->c */ + return dns_name_compare_func(a, b) < 0 && + dns_name_compare_func(b, c) < 0; + else + /* <--b--c a--b--> */ + return dns_name_compare_func(b, c) < 0 || + dns_name_compare_func(a, b) < 0; +} + int dns_name_reverse(int family, const union in_addr_union *a, char **ret) { const uint8_t *p; int r; diff --git a/src/shared/dns-domain.h b/src/shared/dns-domain.h index 00caf5d700..bd50ad3e6d 100644 --- a/src/shared/dns-domain.h +++ b/src/shared/dns-domain.h @@ -29,6 +29,7 @@ #define DNS_NAME_MAX 255 int dns_label_unescape(const char **name, char *dest, size_t sz); +int dns_label_unescape_suffix(const char *name, const char **label_end, char *dest, size_t sz); int dns_label_escape(const char *p, size_t l, char **ret); int dns_label_apply_idna(const char *encoded, size_t encoded_size, char *decoded, size_t decoded_max); @@ -49,6 +50,7 @@ unsigned long dns_name_hash_func(const void *s, const uint8_t hash_key[HASH_KEY_ int dns_name_compare_func(const void *a, const void *b); extern const struct hash_ops dns_name_hash_ops; +int dns_name_between(const char *a, const char *b, const char *c); int dns_name_equal(const char *x, const char *y); int dns_name_endswith(const char *name, const char *suffix); diff --git a/src/shared/efivars.c b/src/shared/efivars.c index 0d6ecf52cf..347cd30b09 100644 --- a/src/shared/efivars.c +++ b/src/shared/efivars.c @@ -125,7 +125,19 @@ static int get_os_indications(uint64_t *os_indication) { return r; r = efi_get_variable(EFI_VENDOR_GLOBAL, "OsIndications", NULL, &v, &s); - if (r < 0) + if (r == -ENOENT) { + /* Some firmware implementations that do support + * OsIndications and report that with + * OsIndicationsSupported will remove the + * OsIndications variable when it is unset. Let's + * pretend it's 0 then, to hide this implementation + * detail. Note that this call will return -ENOENT + * then only if the support for OsIndications is + * missing entirely, as determined by + * efi_reboot_to_firmware_supported() above. */ + *os_indication = 0; + return 0; + } else if (r < 0) return r; else if (s != sizeof(uint64_t)) return -EINVAL; diff --git a/src/shared/nss-util.h b/src/shared/nss-util.h index 230a986040..3657aa5d9c 100644 --- a/src/shared/nss-util.h +++ b/src/shared/nss-util.h @@ -24,6 +24,9 @@ #include <nss.h> #include <netdb.h> #include <resolv.h> +#include <pwd.h> +#include <grp.h> + #define NSS_GETHOSTBYNAME_PROTOTYPES(module) \ enum nss_status _nss_##module##_gethostbyname4_r( \ @@ -109,7 +112,8 @@ enum nss_status _nss_##module##_gethostbyname_r( \ NULL, \ NULL); \ return ret; \ -} +} \ +struct __useless_struct_to_allow_trailing_semicolon__ #define NSS_GETHOSTBYADDR_FALLBACKS(module) \ enum nss_status _nss_##module##_gethostbyaddr_r( \ @@ -125,4 +129,29 @@ enum nss_status _nss_##module##_gethostbyaddr_r( \ buffer, buflen, \ errnop, h_errnop, \ NULL); \ -} +} \ +struct __useless_struct_to_allow_trailing_semicolon__ + +#define NSS_GETPW_PROTOTYPES(module) \ +enum nss_status _nss_##module##_getpwnam_r( \ + const char *name, \ + struct passwd *pwd, \ + char *buffer, size_t buflen, \ + int *errnop) _public_; \ +enum nss_status _nss_mymachines_getpwuid_r( \ + uid_t uid, \ + struct passwd *pwd, \ + char *buffer, size_t buflen, \ + int *errnop) _public_ + +#define NSS_GETGR_PROTOTYPES(module) \ +enum nss_status _nss_##module##_getgrnam_r( \ + const char *name, \ + struct group *gr, \ + char *buffer, size_t buflen, \ + int *errnop) _public_; \ +enum nss_status _nss_##module##_getgrgid_r( \ + gid_t gid, \ + struct group *gr, \ + char *buffer, size_t buflen, \ + int *errnop) _public_ diff --git a/src/shared/sysctl-util.c b/src/shared/sysctl-util.c index 55f4e48601..1de0b94fd5 100644 --- a/src/shared/sysctl-util.c +++ b/src/shared/sysctl-util.c @@ -66,7 +66,7 @@ int sysctl_write(const char *property, const char *value) { log_debug("Setting '%s' to '%s'", property, value); p = strjoina("/proc/sys/", property); - return write_string_file(p, value); + return write_string_file(p, value, 0); } int sysctl_read(const char *property, char **content) { |