summaryrefslogtreecommitdiff
path: root/src/shared
diff options
context:
space:
mode:
Diffstat (limited to 'src/shared')
-rw-r--r--src/shared/bus-util.h11
-rw-r--r--src/shared/dns-domain.c95
-rw-r--r--src/shared/dns-domain.h2
-rw-r--r--src/shared/efivars.c14
-rw-r--r--src/shared/nss-util.h33
-rw-r--r--src/shared/sysctl-util.c2
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) {