diff options
Diffstat (limited to 'src/libsystemd')
25 files changed, 831 insertions, 493 deletions
diff --git a/src/libsystemd/libsystemd.sym b/src/libsystemd/libsystemd.sym index 809db1f6cc..7bf1d66dde 100644 --- a/src/libsystemd/libsystemd.sym +++ b/src/libsystemd/libsystemd.sym @@ -459,3 +459,11 @@ global: sd_event_source_get_signal; sd_event_source_get_child_pid; } LIBSYSTEMD_220; + +LIBSYSTEMD_222 { +global: + /* sd-bus */ + sd_bus_emit_object_added; + sd_bus_emit_object_removed; + sd_bus_flush_close_unref; +} LIBSYSTEMD_221; diff --git a/src/libsystemd/sd-bus/GVARIANT-SERIALIZATION b/src/libsystemd/sd-bus/GVARIANT-SERIALIZATION index 859e2715f9..6aeb11364a 100644 --- a/src/libsystemd/sd-bus/GVARIANT-SERIALIZATION +++ b/src/libsystemd/sd-bus/GVARIANT-SERIALIZATION @@ -25,8 +25,8 @@ The header consists of the following: = 12 bytes -This header is then followed by the the fields array, whose first -value is a 32bit array size. +This header is then followed by the fields array, whose first value is +a 32bit array size. When using GVariant we keep the basic structure in place, only slightly alter the header, and define protocol version '2'. The new diff --git a/src/libsystemd/sd-bus/bus-common-errors.h b/src/libsystemd/sd-bus/bus-common-errors.h index b17b62ac93..f2092795f4 100644 --- a/src/libsystemd/sd-bus/bus-common-errors.h +++ b/src/libsystemd/sd-bus/bus-common-errors.h @@ -46,6 +46,8 @@ #define BUS_ERROR_NO_MACHINE_FOR_PID "org.freedesktop.machine1.NoMachineForPID" #define BUS_ERROR_MACHINE_EXISTS "org.freedesktop.machine1.MachineExists" #define BUS_ERROR_NO_PRIVATE_NETWORKING "org.freedesktop.machine1.NoPrivateNetworking" +#define BUS_ERROR_NO_SUCH_USER_MAPPING "org.freedesktop.machine1.NoSuchUserMapping" +#define BUS_ERROR_NO_SUCH_GROUP_MAPPING "org.freedesktop.machine1.NoSuchGroupMapping" #define BUS_ERROR_NO_SUCH_SESSION "org.freedesktop.login1.NoSuchSession" #define BUS_ERROR_NO_SESSION_FOR_PID "org.freedesktop.login1.NoSessionForPID" @@ -58,6 +60,7 @@ #define BUS_ERROR_DEVICE_NOT_TAKEN "org.freedesktop.login1.DeviceNotTaken" #define BUS_ERROR_OPERATION_IN_PROGRESS "org.freedesktop.login1.OperationInProgress" #define BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED "org.freedesktop.login1.SleepVerbNotSupported" +#define BUS_ERROR_SESSION_BUSY "org.freedesktop.login1.SessionBusy" #define BUS_ERROR_AUTOMATIC_TIME_SYNC_ENABLED "org.freedesktop.timedate1.AutomaticTimeSyncEnabled" diff --git a/src/libsystemd/sd-bus/bus-control.c b/src/libsystemd/sd-bus/bus-control.c index 7a59702cb2..c53666ddd0 100644 --- a/src/libsystemd/sd-bus/bus-control.c +++ b/src/libsystemd/sd-bus/bus-control.c @@ -1131,7 +1131,7 @@ static int add_name_change_match(sd_bus *bus, /* If the old name is unset or empty, then * this can match against added names */ - if (!old_owner || old_owner[0] == 0) { + if (isempty(old_owner)) { item->type = KDBUS_ITEM_NAME_ADD; r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m); @@ -1141,7 +1141,7 @@ static int add_name_change_match(sd_bus *bus, /* If the new name is unset or empty, then * this can match against removed names */ - if (!new_owner || new_owner[0] == 0) { + if (isempty(new_owner)) { item->type = KDBUS_ITEM_NAME_REMOVE; r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m); @@ -1185,8 +1185,10 @@ static int add_name_change_match(sd_bus *bus, /* If the old name is unset or empty, then this can * match against added ids */ - if (!old_owner || old_owner[0] == 0) { + if (isempty(old_owner)) { item->type = KDBUS_ITEM_ID_ADD; + if (!isempty(new_owner)) + item->id_change.id = new_owner_id; r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m); if (r < 0) @@ -1195,8 +1197,10 @@ static int add_name_change_match(sd_bus *bus, /* If thew new name is unset or empty, then this can * match against removed ids */ - if (!new_owner || new_owner[0] == 0) { + if (isempty(new_owner)) { item->type = KDBUS_ITEM_ID_REMOVE; + if (!isempty(old_owner)) + item->id_change.id = old_owner_id; r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m); if (r < 0) @@ -1219,7 +1223,7 @@ int bus_add_match_internal_kernel( size_t sz; const char *sender = NULL; size_t sender_length = 0; - uint64_t src_id = KDBUS_MATCH_ID_ANY; + uint64_t src_id = KDBUS_MATCH_ID_ANY, dst_id = KDBUS_MATCH_ID_ANY; bool using_bloom = false; unsigned i; bool matches_name_change = true; @@ -1332,13 +1336,25 @@ int bus_add_match_internal_kernel( break; } - case BUS_MATCH_DESTINATION: - /* The bloom filter does not include - the destination, since it is only - available for broadcast messages - which do not carry a destination - since they are undirected. */ + case BUS_MATCH_DESTINATION: { + /* + * Kernel only supports matching on destination IDs, but + * not on destination names. So just skip the + * destination name restriction and verify it in + * user-space on retrieval. + */ + r = bus_kernel_parse_unique_name(c->value_str, &dst_id); + if (r < 0) + return r; + else if (r > 0) + sz += ALIGN8(offsetof(struct kdbus_item, id) + sizeof(uint64_t)); + + /* if not a broadcast, it cannot be a name-change */ + if (r <= 0 || dst_id != KDBUS_DST_ID_BROADCAST) + matches_name_change = false; + break; + } case BUS_MATCH_ROOT: case BUS_MATCH_VALUE: @@ -1365,6 +1381,13 @@ int bus_add_match_internal_kernel( item = KDBUS_ITEM_NEXT(item); } + if (dst_id != KDBUS_MATCH_ID_ANY) { + item->size = offsetof(struct kdbus_item, id) + sizeof(uint64_t); + item->type = KDBUS_ITEM_DST_ID; + item->id = dst_id; + item = KDBUS_ITEM_NEXT(item); + } + if (using_bloom) { item->size = offsetof(struct kdbus_item, data64) + bus->bloom_size; item->type = KDBUS_ITEM_BLOOM_MASK; diff --git a/src/libsystemd/sd-bus/bus-kernel.c b/src/libsystemd/sd-bus/bus-kernel.c index f08db2da89..6ac5ebc3da 100644 --- a/src/libsystemd/sd-bus/bus-kernel.c +++ b/src/libsystemd/sd-bus/bus-kernel.c @@ -1332,8 +1332,7 @@ static int bus_kernel_translate_message(sd_bus *bus, struct kdbus_msg *k) { KDBUS_ITEM_FOREACH(d, k, items) { if (d->type == KDBUS_ITEM_TIMESTAMP) ts = &d->timestamp; - - if (d->type >= _KDBUS_ITEM_KERNEL_BASE && d->type < _KDBUS_ITEM_KERNEL_BASE + ELEMENTSOF(translate)) { + else if (d->type >= _KDBUS_ITEM_KERNEL_BASE && d->type < _KDBUS_ITEM_KERNEL_BASE + ELEMENTSOF(translate)) { if (found) return -EBADMSG; found = d; @@ -1385,15 +1384,16 @@ int bus_kernel_read_message(sd_bus *bus, bool hint_priority, int64_t priority) { r = 0; } - } else if (k->payload_type == KDBUS_PAYLOAD_KERNEL) + if (r <= 0) + close_kdbus_msg(bus, k); + } else if (k->payload_type == KDBUS_PAYLOAD_KERNEL) { r = bus_kernel_translate_message(bus, k); - else { + close_kdbus_msg(bus, k); + } else { log_debug("Ignoring message with unknown payload type %llu.", (unsigned long long) k->payload_type); r = 0; - } - - if (r <= 0) close_kdbus_msg(bus, k); + } return r < 0 ? r : 1; } diff --git a/src/libsystemd/sd-bus/bus-message.c b/src/libsystemd/sd-bus/bus-message.c index 983e2f62cd..18685be8ff 100644 --- a/src/libsystemd/sd-bus/bus-message.c +++ b/src/libsystemd/sd-bus/bus-message.c @@ -2161,6 +2161,7 @@ static int bus_message_close_variant(sd_bus_message *m, struct bus_container *c) } static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c, bool add_offset) { + bool fixed_size = true; size_t n_variable = 0; unsigned i = 0; const char *p; @@ -2196,6 +2197,8 @@ static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c, /* We need to add an offset for each item that has a * variable size and that is not the last one in the * list */ + if (r == 0) + fixed_size = false; if (r == 0 && p[n] != 0) n_variable++; @@ -2207,7 +2210,19 @@ static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c, assert(c->need_offsets || n_variable == 0); if (n_variable <= 0) { - a = message_extend_body(m, 1, 0, add_offset, false); + int alignment = 1; + + /* Structures with fixed-size members only have to be + * fixed-size themselves. But gvariant requires all fixed-size + * elements to be sized a multiple of their alignment. Hence, + * we must *always* add final padding after the last member so + * the overall size of the structure is properly aligned. */ + if (fixed_size) + alignment = bus_gvariant_get_alignment(strempty(c->signature)); + + assert(alignment > 0); + + a = message_extend_body(m, alignment, 0, add_offset, false); if (!a) return -ENOMEM; } else { diff --git a/src/libsystemd/sd-bus/bus-objects.c b/src/libsystemd/sd-bus/bus-objects.c index e4bbd880e5..c25293e5e9 100644 --- a/src/libsystemd/sd-bus/bus-objects.c +++ b/src/libsystemd/sd-bus/bus-objects.c @@ -68,6 +68,12 @@ static int node_vtable_get_userdata( return 1; } +static void *vtable_method_convert_userdata(const sd_bus_vtable *p, void *u) { + assert(p); + + return (uint8_t*) u + p->x.method.offset; +} + static void *vtable_property_convert_userdata(const sd_bus_vtable *p, void *u) { assert(p); @@ -167,6 +173,7 @@ static int add_subtree_to_set( sd_bus *bus, const char *prefix, struct node *n, + bool skip_subhierarchies, Set *s, sd_bus_error *error) { @@ -198,11 +205,13 @@ static int add_subtree_to_set( if (r < 0 && r != -EEXIST) return r; - r = add_subtree_to_set(bus, prefix, i, s, error); - if (r < 0) - return r; - if (bus->nodes_modified) - return 0; + if (!skip_subhierarchies || !i->object_managers) { + r = add_subtree_to_set(bus, prefix, i, skip_subhierarchies, s, error); + if (r < 0) + return r; + if (bus->nodes_modified) + return 0; + } } return 0; @@ -212,6 +221,7 @@ static int get_child_nodes( sd_bus *bus, const char *prefix, struct node *n, + bool skip_subhierarchies, Set **_s, sd_bus_error *error) { @@ -227,7 +237,7 @@ static int get_child_nodes( if (!s) return -ENOMEM; - r = add_subtree_to_set(bus, prefix, n, s, error); + r = add_subtree_to_set(bus, prefix, n, skip_subhierarchies, s, error); if (r < 0) { set_free_free(s); return r; @@ -360,6 +370,8 @@ static int method_callbacks_run( if (bus->nodes_modified) return 0; + u = vtable_method_convert_userdata(c->vtable, u); + *found_object = true; if (c->last_iteration == bus->iteration_counter) @@ -892,7 +904,7 @@ static int process_introspect( assert(n); assert(found_object); - r = get_child_nodes(bus, m->path, n, &s, &error); + r = get_child_nodes(bus, m->path, n, false, &s, &error); if (r < 0) return bus_maybe_reply_error(m, r, &error); if (bus->nodes_modified) @@ -1158,12 +1170,16 @@ static int process_get_managed_objects( if (require_fallback || !n->object_managers) return 0; - r = get_child_nodes(bus, m->path, n, &s, &error); + r = get_child_nodes(bus, m->path, n, true, &s, &error); if (r < 0) return r; if (bus->nodes_modified) return 0; + r = set_put_strdup(s, m->path); + if (r < 0) + return r; + r = sd_bus_message_new_method_return(m, &reply); if (r < 0) return r; @@ -1412,7 +1428,7 @@ static struct node *bus_node_allocate(sd_bus *bus, const char *path) { e = strrchr(path, '/'); assert(e); - p = strndupa(path, MAX(1, path - e)); + p = strndupa(path, MAX(1, e - path)); parent = bus_node_allocate(bus, p); if (!parent) @@ -1463,6 +1479,32 @@ void bus_node_gc(sd_bus *b, struct node *n) { free(n); } +static int bus_find_parent_object_manager(sd_bus *bus, struct node **out, const char *path) { + struct node *n; + + assert(bus); + assert(path); + + n = hashmap_get(bus->nodes, path); + if (!n) { + char *prefix; + + prefix = alloca(strlen(path) + 1); + OBJECT_PATH_FOREACH_PREFIX(prefix, path) { + n = hashmap_get(bus->nodes, prefix); + if (n) + break; + } + } + + while (n && !n->object_managers) + n = n->parent; + + if (out) + *out = n; + return !!n; +} + static int bus_add_object( sd_bus *bus, sd_bus_slot **slot, @@ -2261,10 +2303,11 @@ static int object_added_append_all(sd_bus *bus, sd_bus_message *m, const char *p return 0; } -int sd_bus_emit_object_added(sd_bus *bus, const char *path) { +_public_ int sd_bus_emit_object_added(sd_bus *bus, const char *path) { BUS_DONT_DESTROY(bus); _cleanup_bus_message_unref_ sd_bus_message *m = NULL; + struct node *object_manager; int r; /* @@ -2285,11 +2328,17 @@ int sd_bus_emit_object_added(sd_bus *bus, const char *path) { if (!BUS_IS_OPEN(bus->state)) return -ENOTCONN; + r = bus_find_parent_object_manager(bus, &object_manager, path); + if (r < 0) + return r; + if (r == 0) + return -ESRCH; + do { bus->nodes_modified = false; m = sd_bus_message_unref(m); - r = sd_bus_message_new_signal(bus, &m, path, "org.freedesktop.DBus.ObjectManager", "InterfacesAdded"); + r = sd_bus_message_new_signal(bus, &m, object_manager->path, "org.freedesktop.DBus.ObjectManager", "InterfacesAdded"); if (r < 0) return r; @@ -2424,10 +2473,11 @@ static int object_removed_append_all(sd_bus *bus, sd_bus_message *m, const char return 0; } -int sd_bus_emit_object_removed(sd_bus *bus, const char *path) { +_public_ int sd_bus_emit_object_removed(sd_bus *bus, const char *path) { BUS_DONT_DESTROY(bus); _cleanup_bus_message_unref_ sd_bus_message *m = NULL; + struct node *object_manager; int r; /* @@ -2448,11 +2498,17 @@ int sd_bus_emit_object_removed(sd_bus *bus, const char *path) { if (!BUS_IS_OPEN(bus->state)) return -ENOTCONN; + r = bus_find_parent_object_manager(bus, &object_manager, path); + if (r < 0) + return r; + if (r == 0) + return -ESRCH; + do { bus->nodes_modified = false; m = sd_bus_message_unref(m); - r = sd_bus_message_new_signal(bus, &m, path, "org.freedesktop.DBus.ObjectManager", "InterfacesRemoved"); + r = sd_bus_message_new_signal(bus, &m, object_manager->path, "org.freedesktop.DBus.ObjectManager", "InterfacesRemoved"); if (r < 0) return r; @@ -2584,6 +2640,7 @@ _public_ int sd_bus_emit_interfaces_added_strv(sd_bus *bus, const char *path, ch BUS_DONT_DESTROY(bus); _cleanup_bus_message_unref_ sd_bus_message *m = NULL; + struct node *object_manager; char **i; int r; @@ -2597,11 +2654,17 @@ _public_ int sd_bus_emit_interfaces_added_strv(sd_bus *bus, const char *path, ch if (strv_isempty(interfaces)) return 0; + r = bus_find_parent_object_manager(bus, &object_manager, path); + if (r < 0) + return r; + if (r == 0) + return -ESRCH; + do { bus->nodes_modified = false; m = sd_bus_message_unref(m); - r = sd_bus_message_new_signal(bus, &m, path, "org.freedesktop.DBus.ObjectManager", "InterfacesAdded"); + r = sd_bus_message_new_signal(bus, &m, object_manager->path, "org.freedesktop.DBus.ObjectManager", "InterfacesAdded"); if (r < 0) return r; @@ -2661,6 +2724,7 @@ _public_ int sd_bus_emit_interfaces_added(sd_bus *bus, const char *path, const c _public_ int sd_bus_emit_interfaces_removed_strv(sd_bus *bus, const char *path, char **interfaces) { _cleanup_bus_message_unref_ sd_bus_message *m = NULL; + struct node *object_manager; int r; assert_return(bus, -EINVAL); @@ -2673,7 +2737,13 @@ _public_ int sd_bus_emit_interfaces_removed_strv(sd_bus *bus, const char *path, if (strv_isempty(interfaces)) return 0; - r = sd_bus_message_new_signal(bus, &m, path, "org.freedesktop.DBus.ObjectManager", "InterfacesRemoved"); + r = bus_find_parent_object_manager(bus, &object_manager, path); + if (r < 0) + return r; + if (r == 0) + return -ESRCH; + + r = sd_bus_message_new_signal(bus, &m, object_manager->path, "org.freedesktop.DBus.ObjectManager", "InterfacesRemoved"); if (r < 0) return r; diff --git a/src/libsystemd/sd-bus/bus-slot.c b/src/libsystemd/sd-bus/bus-slot.c index c452477566..b149ea16da 100644 --- a/src/libsystemd/sd-bus/bus-slot.c +++ b/src/libsystemd/sd-bus/bus-slot.c @@ -273,7 +273,7 @@ _public_ int sd_bus_slot_set_description(sd_bus_slot *slot, const char *descript return free_and_strdup(&slot->description, description); } -_public_ int sd_bus_slot_get_description(sd_bus_slot *slot, char **description) { +_public_ int sd_bus_slot_get_description(sd_bus_slot *slot, const char **description) { assert_return(slot, -EINVAL); assert_return(description, -EINVAL); assert_return(slot->description, -ENXIO); diff --git a/src/libsystemd/sd-bus/bus-socket.c b/src/libsystemd/sd-bus/bus-socket.c index 322d57ddbb..735a775cb4 100644 --- a/src/libsystemd/sd-bus/bus-socket.c +++ b/src/libsystemd/sd-bus/bus-socket.c @@ -264,6 +264,8 @@ static bool line_begins(const char *s, size_t m, const char *word) { static int verify_anonymous_token(sd_bus *b, const char *p, size_t l) { _cleanup_free_ char *token = NULL; + size_t len; + int r; if (!b->anonymous_auth) return 0; @@ -276,11 +278,12 @@ static int verify_anonymous_token(sd_bus *b, const char *p, size_t l) { if (l % 2 != 0) return 0; - token = unhexmem(p, l); - if (!token) - return -ENOMEM; - if (memchr(token, 0, l/2)) + r = unhexmem(p, l, (void **) &token, &len); + if (r < 0) + return 0; + + if (memchr(token, 0, len)) return 0; return !!utf8_is_valid(token); @@ -288,6 +291,7 @@ static int verify_anonymous_token(sd_bus *b, const char *p, size_t l) { static int verify_external_token(sd_bus *b, const char *p, size_t l) { _cleanup_free_ char *token = NULL; + size_t len; uid_t u; int r; @@ -307,11 +311,11 @@ static int verify_external_token(sd_bus *b, const char *p, size_t l) { if (l % 2 != 0) return 0; - token = unhexmem(p, l); - if (!token) - return -ENOMEM; + r = unhexmem(p, l, (void**) &token, &len); + if (r < 0) + return 0; - if (memchr(token, 0, l/2)) + if (memchr(token, 0, len)) return 0; r = parse_uid(token, &u); diff --git a/src/libsystemd/sd-bus/busctl.c b/src/libsystemd/sd-bus/busctl.c index 39caa4e7d6..6aaaf0e5ec 100644 --- a/src/libsystemd/sd-bus/busctl.c +++ b/src/libsystemd/sd-bus/busctl.c @@ -1137,6 +1137,7 @@ static int monitor(sd_bus *bus, char *argv[], int (*dump)(sd_bus_message *m, FIL if (m) { dump(m, stdout); + fflush(stdout); if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected") > 0) { log_info("Connection terminated, exiting."); @@ -1973,7 +1974,7 @@ static int busctl_main(sd_bus *bus, int argc, char *argv[]) { } int main(int argc, char *argv[]) { - _cleanup_bus_close_unref_ sd_bus *bus = NULL; + _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL; int r; log_parse_environment(); diff --git a/src/libsystemd/sd-bus/kdbus.h b/src/libsystemd/sd-bus/kdbus.h index 00a6e142c9..ecffc6b13c 100644 --- a/src/libsystemd/sd-bus/kdbus.h +++ b/src/libsystemd/sd-bus/kdbus.h @@ -374,6 +374,7 @@ enum kdbus_item_type { KDBUS_ITEM_ATTACH_FLAGS_RECV, KDBUS_ITEM_ID, KDBUS_ITEM_NAME, + KDBUS_ITEM_DST_ID, /* keep these item types in sync with KDBUS_ATTACH_* flags */ _KDBUS_ITEM_ATTACH_BASE = 0x1000, diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c index 5dd6468707..0ca225c617 100644 --- a/src/libsystemd/sd-bus/sd-bus.c +++ b/src/libsystemd/sd-bus/sd-bus.c @@ -1428,6 +1428,17 @@ _public_ void sd_bus_close(sd_bus *bus) { * ioctl on the fd when they are freed. */ } +_public_ sd_bus* sd_bus_flush_close_unref(sd_bus *bus) { + + if (!bus) + return NULL; + + sd_bus_flush(bus); + sd_bus_close(bus); + + return sd_bus_unref(bus); +} + static void bus_enter_closing(sd_bus *bus) { assert(bus); diff --git a/src/libsystemd/sd-bus/test-bus-chat.c b/src/libsystemd/sd-bus/test-bus-chat.c index 046e999008..754335b5e7 100644 --- a/src/libsystemd/sd-bus/test-bus-chat.c +++ b/src/libsystemd/sd-bus/test-bus-chat.c @@ -262,7 +262,7 @@ fail: static void* client1(void*p) { _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; - _cleanup_bus_close_unref_ sd_bus *bus = NULL; + _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL; _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; const char *hello; int r; @@ -361,7 +361,7 @@ static int quit_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_er static void* client2(void*p) { _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL; - _cleanup_bus_close_unref_ sd_bus *bus = NULL; + _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL; _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; bool quit = false; const char *mid; diff --git a/src/libsystemd/sd-bus/test-bus-gvariant.c b/src/libsystemd/sd-bus/test-bus-gvariant.c index 22ea00c2fb..9b7dd2e499 100644 --- a/src/libsystemd/sd-bus/test-bus-gvariant.c +++ b/src/libsystemd/sd-bus/test-bus-gvariant.c @@ -132,7 +132,7 @@ static void test_bus_gvariant_get_alignment(void) { static void test_marshal(void) { _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *n = NULL; - _cleanup_bus_close_unref_ sd_bus *bus = NULL; + _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL; _cleanup_free_ void *blob; size_t sz; int r; diff --git a/src/libsystemd/sd-bus/test-bus-marshal.c b/src/libsystemd/sd-bus/test-bus-marshal.c index a866a56179..59deaea89f 100644 --- a/src/libsystemd/sd-bus/test-bus-marshal.c +++ b/src/libsystemd/sd-bus/test-bus-marshal.c @@ -131,6 +131,9 @@ int main(int argc, char *argv[]) { r = sd_bus_message_append(m, "a{yv}", 2, 3, "s", "foo", 5, "s", "waldo"); assert_se(r >= 0); + r = sd_bus_message_append(m, "y(ty)y(yt)y", 8, 777ULL, 7, 9, 77, 7777ULL, 10); + assert_se(r >= 0); + r = sd_bus_message_append(m, "ba(ss)", 255, 3, "aaa", "1", "bbb", "2", "ccc", "3"); assert_se(r >= 0); @@ -252,6 +255,22 @@ int main(int argc, char *argv[]) { assert_se(v == 5); assert_se(streq(y, "waldo")); + r = sd_bus_message_read(m, "y(ty)", &v, &u64, &u); + assert_se(r > 0); + assert_se(v == 8); + assert_se(u64 == 777); + assert_se(u == 7); + + r = sd_bus_message_read(m, "y(yt)", &v, &u, &u64); + assert_se(r > 0); + assert_se(v == 9); + assert_se(u == 77); + assert_se(u64 == 7777); + + r = sd_bus_message_read(m, "y", &v); + assert_se(r > 0); + assert_se(v == 10); + r = sd_bus_message_read(m, "ba(ss)", &boolean, 3, &x, &y, &a, &b, &c, &d); assert_se(r > 0); assert_se(boolean); @@ -331,7 +350,7 @@ int main(int argc, char *argv[]) { assert_se(sd_bus_message_verify_type(m, 'a', "{yv}") > 0); - r = sd_bus_message_skip(m, "a{yv}"); + r = sd_bus_message_skip(m, "a{yv}y(ty)y(yt)y"); assert_se(r >= 0); assert_se(sd_bus_message_verify_type(m, 'b', NULL) > 0); diff --git a/src/libsystemd/sd-bus/test-bus-match.c b/src/libsystemd/sd-bus/test-bus-match.c index a1687b1c7b..83cb5c62c2 100644 --- a/src/libsystemd/sd-bus/test-bus-match.c +++ b/src/libsystemd/sd-bus/test-bus-match.c @@ -92,7 +92,7 @@ int main(int argc, char *argv[]) { }; _cleanup_bus_message_unref_ sd_bus_message *m = NULL; - _cleanup_bus_close_unref_ sd_bus *bus = NULL; + _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL; enum bus_match_node_type i; sd_bus_slot slots[19]; int r; diff --git a/src/libsystemd/sd-bus/test-bus-objects.c b/src/libsystemd/sd-bus/test-bus-objects.c index 52952603e4..359984c7f3 100644 --- a/src/libsystemd/sd-bus/test-bus-objects.c +++ b/src/libsystemd/sd-bus/test-bus-objects.c @@ -115,14 +115,13 @@ static int set_handler(sd_bus *bus, const char *path, const char *interface, con static int value_handler(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { _cleanup_free_ char *s = NULL; - const char *x; int r; assert_se(asprintf(&s, "object %p, path %s", userdata, path) >= 0); r = sd_bus_message_append(reply, "s", s); assert_se(r >= 0); - assert_se(x = startswith(path, "/value/")); + assert_se(startswith(path, "/value/") != NULL || strcmp(path, "/value") == 0); assert_se(PTR_TO_UINT(userdata) == 30); @@ -154,7 +153,7 @@ static int notify_test2(sd_bus_message *m, void *userdata, sd_bus_error *error) static int emit_interfaces_added(sd_bus_message *m, void *userdata, sd_bus_error *error) { int r; - assert_se(sd_bus_emit_interfaces_added(sd_bus_message_get_bus(m), m->path, "org.freedesktop.systemd.test", NULL) >= 0); + assert_se(sd_bus_emit_interfaces_added(sd_bus_message_get_bus(m), "/value/a/x", "org.freedesktop.systemd.ValueTest", NULL) >= 0); r = sd_bus_reply_method_return(m, NULL); assert_se(r >= 0); @@ -165,7 +164,7 @@ static int emit_interfaces_added(sd_bus_message *m, void *userdata, sd_bus_error static int emit_interfaces_removed(sd_bus_message *m, void *userdata, sd_bus_error *error) { int r; - assert_se(sd_bus_emit_interfaces_removed(sd_bus_message_get_bus(m), m->path, "org.freedesktop.systemd.test", NULL) >= 0); + assert_se(sd_bus_emit_interfaces_removed(sd_bus_message_get_bus(m), "/value/a/x", "org.freedesktop.systemd.ValueTest", NULL) >= 0); r = sd_bus_reply_method_return(m, NULL); assert_se(r >= 0); @@ -176,7 +175,7 @@ static int emit_interfaces_removed(sd_bus_message *m, void *userdata, sd_bus_err static int emit_object_added(sd_bus_message *m, void *userdata, sd_bus_error *error) { int r; - assert_se(sd_bus_emit_object_added(sd_bus_message_get_bus(m), m->path) >= 0); + assert_se(sd_bus_emit_object_added(sd_bus_message_get_bus(m), "/value/a/x") >= 0); r = sd_bus_reply_method_return(m, NULL); assert_se(r >= 0); @@ -187,7 +186,7 @@ static int emit_object_added(sd_bus_message *m, void *userdata, sd_bus_error *er static int emit_object_removed(sd_bus_message *m, void *userdata, sd_bus_error *error) { int r; - assert_se(sd_bus_emit_object_removed(sd_bus_message_get_bus(m), m->path) >= 0); + assert_se(sd_bus_emit_object_removed(sd_bus_message_get_bus(m), "/value/a/x") >= 0); r = sd_bus_reply_method_return(m, NULL); assert_se(r >= 0); @@ -229,6 +228,14 @@ static int enumerator_callback(sd_bus *bus, const char *path, void *userdata, ch return 1; } +static int enumerator2_callback(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) { + + if (object_path_startswith("/value/a", path)) + assert_se(*nodes = strv_new("/value/a/x", "/value/a/y", "/value/a/z", NULL)); + + return 1; +} + static void *server(void *p) { struct context *c = p; sd_bus *bus = NULL; @@ -247,7 +254,9 @@ static void *server(void *p) { assert_se(sd_bus_add_object_vtable(bus, NULL, "/foo", "org.freedesktop.systemd.test2", vtable, c) >= 0); assert_se(sd_bus_add_fallback_vtable(bus, NULL, "/value", "org.freedesktop.systemd.ValueTest", vtable2, NULL, UINT_TO_PTR(20)) >= 0); assert_se(sd_bus_add_node_enumerator(bus, NULL, "/value", enumerator_callback, NULL) >= 0); + assert_se(sd_bus_add_node_enumerator(bus, NULL, "/value/a", enumerator2_callback, NULL) >= 0); assert_se(sd_bus_add_object_manager(bus, NULL, "/value") >= 0); + assert_se(sd_bus_add_object_manager(bus, NULL, "/value/a") >= 0); assert_se(sd_bus_start(bus) >= 0); diff --git a/src/libsystemd/sd-bus/test-bus-proxy.c b/src/libsystemd/sd-bus/test-bus-proxy.c new file mode 100644 index 0000000000..369c2f331c --- /dev/null +++ b/src/libsystemd/sd-bus/test-bus-proxy.c @@ -0,0 +1,109 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/*** + This file is part of systemd. + + Copyright 2015 David Herrmann <dh.herrmann@gmail.com> + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#include <errno.h> +#include <fcntl.h> +#include <stdlib.h> + +#include "util.h" +#include "log.h" + +#include "sd-bus.h" +#include "bus-kernel.h" +#include "bus-util.h" +#include "bus-dump.h" + +typedef struct { + const char *sender; + int matched_acquired; +} TestProxyMatch; + +static int test_proxy_acquired(sd_bus_message *m, void *userdata, sd_bus_error *error) { + TestProxyMatch *match = userdata; + const char *name; + int r; + + r = sd_bus_message_read(m, "s", &name); + assert_se(r >= 0); + + if (!streq_ptr(match->sender, name)) + return 0; + + ++match->matched_acquired; + return 1; +} + +static void test_proxy_matched(void) { + _cleanup_bus_flush_close_unref_ sd_bus *a = NULL; + TestProxyMatch match = {}; + int r; + + /* open bus 'a' */ + + r = sd_bus_new(&a); + assert_se(r >= 0); + + r = sd_bus_set_address(a, "unix:path=/var/run/dbus/system_bus_socket"); + assert_se(r >= 0); + + r = sd_bus_set_bus_client(a, true); + assert_se(r >= 0); + + r = sd_bus_start(a); + assert_se(r >= 0); + + r = sd_bus_add_match(a, NULL, + "type='signal'," + "member='NameAcquired'", + test_proxy_acquired, &match); + assert_se(r >= 0); + + r = sd_bus_get_unique_name(a, &match.sender); + assert_se(r >= 0); + + /* barrier to guarantee proxy/dbus-daemon handled the previous data */ + r = sd_bus_call_method(a, + "org.freedesktop.DBus", + "/org/freedesktop/DBus", + "org.freedesktop.DBus", + "GetId", + NULL, NULL, NULL); + assert_se(r >= 0); + + /* now we can be sure the Name* signals were sent */ + do { + r = sd_bus_process(a, NULL); + } while (r > 0); + assert_se(r == 0); + + assert_se(match.matched_acquired == 1); +} + +int main(int argc, char **argv) { + if (access("/var/run/dbus/system_bus_socket", F_OK) < 0) + return EXIT_TEST_SKIP; + + log_parse_environment(); + + test_proxy_matched(); + + return EXIT_SUCCESS; +} diff --git a/src/libsystemd/sd-device/sd-device.c b/src/libsystemd/sd-device/sd-device.c index b274f71093..7cea5a0746 100644 --- a/src/libsystemd/sd-device/sd-device.c +++ b/src/libsystemd/sd-device/sd-device.c @@ -791,6 +791,9 @@ _public_ int sd_device_get_subsystem(sd_device *device, const char **ret) { device->subsystem_set = true; } + if (!device->subsystem) + return -ENOENT; + *ret = device->subsystem; return 0; @@ -908,6 +911,9 @@ _public_ int sd_device_get_driver(sd_device *device, const char **ret) { return log_debug_errno(r, "sd-device: could not set driver for %s: %m", device->devpath); } + if (!device->driver) + return -ENOENT; + *ret = device->driver; return 0; @@ -1002,6 +1008,8 @@ _public_ int sd_device_get_sysname(sd_device *device, const char **ret) { return r; } + assert_return(device->sysname, -ENOENT); + *ret = device->sysname; return 0; diff --git a/src/libsystemd/sd-id128/libsystemd-id128.pc.in b/src/libsystemd/sd-id128/libsystemd-id128.pc.in deleted file mode 100644 index bb65ffde33..0000000000 --- a/src/libsystemd/sd-id128/libsystemd-id128.pc.in +++ /dev/null @@ -1,18 +0,0 @@ -# This file is part of systemd. -# -# systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by -# the Free Software Foundation; either version 2.1 of the License, or -# (at your option) any later version. - -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -includedir=@includedir@ - -Name: systemd -Description: systemd 128 Bit ID Utility Library -URL: @PACKAGE_URL@ -Version: @PACKAGE_VERSION@ -Libs: -L${libdir} -lsystemd-id128 -Cflags: -I${includedir} diff --git a/src/libsystemd/sd-netlink/netlink-internal.h b/src/libsystemd/sd-netlink/netlink-internal.h index 7290f4e875..4026e2c341 100644 --- a/src/libsystemd/sd-netlink/netlink-internal.h +++ b/src/libsystemd/sd-netlink/netlink-internal.h @@ -92,18 +92,27 @@ struct sd_netlink { sd_event *event; }; +struct netlink_attribute { + size_t offset; /* offset from hdr to attribute */ + bool nested:1; + bool net_byteorder:1; +}; + +struct netlink_container { + const struct NLTypeSystem *type_system; /* the type system of the container */ + size_t offset; /* offset from hdr to the start of the container */ + struct netlink_attribute *attributes; + unsigned short n_attributes; /* number of attributes in container */ +}; + struct sd_netlink_message { RefCount n_ref; sd_netlink *rtnl; struct nlmsghdr *hdr; - const struct NLTypeSystem *(container_type_system[RTNL_CONTAINER_DEPTH]); /* the type of the container and all its parents */ - size_t container_offsets[RTNL_CONTAINER_DEPTH]; /* offset from hdr to each container's start */ + struct netlink_container containers[RTNL_CONTAINER_DEPTH]; unsigned n_containers; /* number of containers */ - size_t next_rta_offset; /* offset from hdr to next rta */ - size_t *rta_offset_tb[RTNL_CONTAINER_DEPTH]; - unsigned short rta_tb_size[RTNL_CONTAINER_DEPTH]; bool sealed:1; bool broadcast:1; @@ -122,14 +131,6 @@ int socket_read_message(sd_netlink *nl); int rtnl_rqueue_make_room(sd_netlink *rtnl); int rtnl_rqueue_partial_make_room(sd_netlink *rtnl); -int rtnl_message_read_internal(sd_netlink_message *m, unsigned short type, void **data); -int rtnl_message_parse(sd_netlink_message *m, - size_t **rta_offset_tb, - unsigned short *rta_tb_size, - int max, - struct rtattr *rta, - unsigned int rt_len); - /* Make sure callbacks don't destroy the rtnl connection */ #define RTNL_DONT_DESTROY(rtnl) \ _cleanup_netlink_unref_ _unused_ sd_netlink *_dont_destroy_##rtnl = sd_netlink_ref(rtnl) diff --git a/src/libsystemd/sd-netlink/netlink-message.c b/src/libsystemd/sd-netlink/netlink-message.c index 87324fc2f7..b0ed2f2882 100644 --- a/src/libsystemd/sd-netlink/netlink-message.c +++ b/src/libsystemd/sd-netlink/netlink-message.c @@ -34,10 +34,11 @@ #include "netlink-internal.h" #include "netlink-types.h" -#define GET_CONTAINER(m, i) ((i) < (m)->n_containers ? (struct rtattr*)((uint8_t*)(m)->hdr + (m)->container_offsets[i]) : NULL) +#define GET_CONTAINER(m, i) ((i) < (m)->n_containers ? (struct rtattr*)((uint8_t*)(m)->hdr + (m)->containers[i].offset) : NULL) #define PUSH_CONTAINER(m, new) (m)->container_offsets[(m)->n_containers ++] = (uint8_t*)(new) - (uint8_t*)(m)->hdr; #define RTA_TYPE(rta) ((rta)->rta_type & NLA_TYPE_MASK) +#define RTA_FLAGS(rta) ((rta)->rta_type & ~NLA_TYPE_MASK) int message_new_empty(sd_netlink *rtnl, sd_netlink_message **ret) { sd_netlink_message *m; @@ -68,15 +69,18 @@ int message_new(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t type) { size_t size; int r; - r = type_system_get_type(NULL, &nl_type, type); + r = type_system_get_type(&type_system_root, &nl_type, type); if (r < 0) return r; + if (type_get_type(nl_type) != NETLINK_TYPE_NESTED) + return -EINVAL; + r = message_new_empty(rtnl, &m); if (r < 0) return r; - size = NLMSG_SPACE(nl_type->size); + size = NLMSG_SPACE(type_get_size(nl_type)); assert(size >= sizeof(struct nlmsghdr)); m->hdr = malloc0(size); @@ -85,7 +89,7 @@ int message_new(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t type) { m->hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; - m->container_type_system[0] = nl_type->type_system; + type_get_type_system(nl_type, &m->containers[0].type_system); m->hdr->nlmsg_len = size; m->hdr->nlmsg_type = type; @@ -126,7 +130,7 @@ sd_netlink_message *sd_netlink_message_unref(sd_netlink_message *m) { free(m->hdr); for (i = 0; i <= m->n_containers; i++) - free(m->rta_offset_tb[i]); + free(m->containers[i].attributes); sd_netlink_message_unref(m->next); @@ -214,18 +218,22 @@ static int add_rtattr(sd_netlink_message *m, unsigned short type, const void *da return offset; } -static int message_attribute_has_type(sd_netlink_message *m, uint16_t attribute_type, uint16_t data_type) { +static int message_attribute_has_type(sd_netlink_message *m, size_t *out_size, uint16_t attribute_type, uint16_t data_type) { const NLType *type; int r; - r = type_system_get_type(m->container_type_system[m->n_containers], &type, attribute_type); + assert(m); + + r = type_system_get_type(m->containers[m->n_containers].type_system, &type, attribute_type); if (r < 0) return r; - if (type->type != data_type) + if (type_get_type(type) != data_type) return -EINVAL; - return type->size; + if (out_size) + *out_size = type_get_size(type); + return 0; } int sd_netlink_message_append_string(sd_netlink_message *m, unsigned short type, const char *data) { @@ -236,11 +244,9 @@ int sd_netlink_message_append_string(sd_netlink_message *m, unsigned short type, assert_return(!m->sealed, -EPERM); assert_return(data, -EINVAL); - r = message_attribute_has_type(m, type, NLA_STRING); + r = message_attribute_has_type(m, &size, type, NETLINK_TYPE_STRING); if (r < 0) return r; - else - size = (size_t)r; if (size) { length = strnlen(data, size+1); @@ -262,7 +268,7 @@ int sd_netlink_message_append_u8(sd_netlink_message *m, unsigned short type, uin assert_return(m, -EINVAL); assert_return(!m->sealed, -EPERM); - r = message_attribute_has_type(m, type, NLA_U8); + r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_U8); if (r < 0) return r; @@ -280,7 +286,7 @@ int sd_netlink_message_append_u16(sd_netlink_message *m, unsigned short type, ui assert_return(m, -EINVAL); assert_return(!m->sealed, -EPERM); - r = message_attribute_has_type(m, type, NLA_U16); + r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_U16); if (r < 0) return r; @@ -297,7 +303,7 @@ int sd_netlink_message_append_u32(sd_netlink_message *m, unsigned short type, ui assert_return(m, -EINVAL); assert_return(!m->sealed, -EPERM); - r = message_attribute_has_type(m, type, NLA_U32); + r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_U32); if (r < 0) return r; @@ -315,7 +321,7 @@ int sd_netlink_message_append_in_addr(sd_netlink_message *m, unsigned short type assert_return(!m->sealed, -EPERM); assert_return(data, -EINVAL); - r = message_attribute_has_type(m, type, NLA_IN_ADDR); + r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_IN_ADDR); if (r < 0) return r; @@ -333,7 +339,7 @@ int sd_netlink_message_append_in6_addr(sd_netlink_message *m, unsigned short typ assert_return(!m->sealed, -EPERM); assert_return(data, -EINVAL); - r = message_attribute_has_type(m, type, NLA_IN_ADDR); + r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_IN_ADDR); if (r < 0) return r; @@ -351,7 +357,7 @@ int sd_netlink_message_append_ether_addr(sd_netlink_message *m, unsigned short t assert_return(!m->sealed, -EPERM); assert_return(data, -EINVAL); - r = message_attribute_has_type(m, type, NLA_ETHER_ADDR); + r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_ETHER_ADDR); if (r < 0) return r; @@ -369,7 +375,7 @@ int sd_netlink_message_append_cache_info(sd_netlink_message *m, unsigned short t assert_return(!m->sealed, -EPERM); assert_return(info, -EINVAL); - r = message_attribute_has_type(m, type, NLA_CACHE_INFO); + r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_CACHE_INFO); if (r < 0) return r; @@ -388,34 +394,31 @@ int sd_netlink_message_open_container(sd_netlink_message *m, unsigned short type assert_return(!m->sealed, -EPERM); assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -ERANGE); - r = message_attribute_has_type(m, type, NLA_NESTED); + r = message_attribute_has_type(m, &size, type, NETLINK_TYPE_NESTED); if (r < 0) { const NLTypeSystemUnion *type_system_union; int family; - r = message_attribute_has_type(m, type, NLA_UNION); + r = message_attribute_has_type(m, &size, type, NETLINK_TYPE_UNION); if (r < 0) return r; - size = (size_t) r; r = sd_rtnl_message_get_family(m, &family); if (r < 0) return r; - r = type_system_get_type_system_union(m->container_type_system[m->n_containers], &type_system_union, type); + r = type_system_get_type_system_union(m->containers[m->n_containers].type_system, &type_system_union, type); if (r < 0) return r; r = type_system_union_protocol_get_type_system(type_system_union, - &m->container_type_system[m->n_containers + 1], + &m->containers[m->n_containers + 1].type_system, family); if (r < 0) return r; } else { - size = (size_t)r; - - r = type_system_get_type_system(m->container_type_system[m->n_containers], - &m->container_type_system[m->n_containers + 1], + r = type_system_get_type_system(m->containers[m->n_containers].type_system, + &m->containers[m->n_containers + 1].type_system, type); if (r < 0) return r; @@ -425,7 +428,7 @@ int sd_netlink_message_open_container(sd_netlink_message *m, unsigned short type if (r < 0) return r; - m->container_offsets[m->n_containers ++] = r; + m->containers[m->n_containers ++].offset = r; return 0; } @@ -437,12 +440,12 @@ int sd_netlink_message_open_container_union(sd_netlink_message *m, unsigned shor assert_return(m, -EINVAL); assert_return(!m->sealed, -EPERM); - r = type_system_get_type_system_union(m->container_type_system[m->n_containers], &type_system_union, type); + r = type_system_get_type_system_union(m->containers[m->n_containers].type_system, &type_system_union, type); if (r < 0) return r; r = type_system_union_get_type_system(type_system_union, - &m->container_type_system[m->n_containers + 1], + &m->containers[m->n_containers + 1].type_system, key); if (r < 0) return r; @@ -452,11 +455,11 @@ int sd_netlink_message_open_container_union(sd_netlink_message *m, unsigned shor return r; /* do we evere need non-null size */ - r = add_rtattr(m, type, NULL, 0); + r = add_rtattr(m, type | NLA_F_NESTED, NULL, 0); if (r < 0) return r; - m->container_offsets[m->n_containers ++] = r; + m->containers[m->n_containers ++].offset = r; return 0; } @@ -467,29 +470,35 @@ int sd_netlink_message_close_container(sd_netlink_message *m) { assert_return(!m->sealed, -EPERM); assert_return(m->n_containers > 0, -EINVAL); - m->container_type_system[m->n_containers] = NULL; + m->containers[m->n_containers].type_system = NULL; m->n_containers --; return 0; } -int rtnl_message_read_internal(sd_netlink_message *m, unsigned short type, void **data) { +static int netlink_message_read_internal(sd_netlink_message *m, unsigned short type, void **data, bool *net_byteorder) { + struct netlink_attribute *attribute; struct rtattr *rta; assert_return(m, -EINVAL); assert_return(m->sealed, -EPERM); assert_return(data, -EINVAL); assert(m->n_containers <= RTNL_CONTAINER_DEPTH); - assert(m->rta_offset_tb[m->n_containers]); - assert(type < m->rta_tb_size[m->n_containers]); + assert(m->containers[m->n_containers].attributes); + assert(type < m->containers[m->n_containers].n_attributes); + + attribute = &m->containers[m->n_containers].attributes[type]; - if(!m->rta_offset_tb[m->n_containers][type]) + if(!attribute->offset) return -ENODATA; - rta = (struct rtattr*)((uint8_t *) m->hdr + m->rta_offset_tb[m->n_containers][type]); + rta = (struct rtattr*)((uint8_t *) m->hdr + attribute->offset); *data = RTA_DATA(rta); + if (net_byteorder) + *net_byteorder = attribute->net_byteorder; + return RTA_PAYLOAD(rta); } @@ -499,11 +508,11 @@ int sd_netlink_message_read_string(sd_netlink_message *m, unsigned short type, c assert_return(m, -EINVAL); - r = message_attribute_has_type(m, type, NLA_STRING); + r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_STRING); if (r < 0) return r; - r = rtnl_message_read_internal(m, type, &attr_data); + r = netlink_message_read_internal(m, type, &attr_data, NULL); if (r < 0) return r; else if (strnlen(attr_data, r) >= (size_t) r) @@ -521,11 +530,11 @@ int sd_netlink_message_read_u8(sd_netlink_message *m, unsigned short type, uint8 assert_return(m, -EINVAL); - r = message_attribute_has_type(m, type, NLA_U8); + r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_U8); if (r < 0) return r; - r = rtnl_message_read_internal(m, type, &attr_data); + r = netlink_message_read_internal(m, type, &attr_data, NULL); if (r < 0) return r; else if ((size_t) r < sizeof(uint8_t)) @@ -538,45 +547,55 @@ int sd_netlink_message_read_u8(sd_netlink_message *m, unsigned short type, uint8 } int sd_netlink_message_read_u16(sd_netlink_message *m, unsigned short type, uint16_t *data) { - int r; void *attr_data; + bool net_byteorder; + int r; assert_return(m, -EINVAL); - r = message_attribute_has_type(m, type, NLA_U16); + r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_U16); if (r < 0) return r; - r = rtnl_message_read_internal(m, type, &attr_data); + r = netlink_message_read_internal(m, type, &attr_data, &net_byteorder); if (r < 0) return r; else if ((size_t) r < sizeof(uint16_t)) return -EIO; - if (data) - *data = *(uint16_t *) attr_data; + if (data) { + if (net_byteorder) + *data = be16toh(*(uint16_t *) attr_data); + else + *data = *(uint16_t *) attr_data; + } return 0; } int sd_netlink_message_read_u32(sd_netlink_message *m, unsigned short type, uint32_t *data) { - int r; void *attr_data; + bool net_byteorder; + int r; assert_return(m, -EINVAL); - r = message_attribute_has_type(m, type, NLA_U32); + r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_U32); if (r < 0) return r; - r = rtnl_message_read_internal(m, type, &attr_data); + r = netlink_message_read_internal(m, type, &attr_data, &net_byteorder); if (r < 0) return r; else if ((size_t)r < sizeof(uint32_t)) return -EIO; - if (data) - *data = *(uint32_t *) attr_data; + if (data) { + if (net_byteorder) + *data = be32toh(*(uint32_t *) attr_data); + else + *data = *(uint32_t *) attr_data; + } return 0; } @@ -587,11 +606,11 @@ int sd_netlink_message_read_ether_addr(sd_netlink_message *m, unsigned short typ assert_return(m, -EINVAL); - r = message_attribute_has_type(m, type, NLA_ETHER_ADDR); + r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_ETHER_ADDR); if (r < 0) return r; - r = rtnl_message_read_internal(m, type, &attr_data); + r = netlink_message_read_internal(m, type, &attr_data, NULL); if (r < 0) return r; else if ((size_t)r < sizeof(struct ether_addr)) @@ -609,11 +628,11 @@ int sd_netlink_message_read_cache_info(sd_netlink_message *m, unsigned short typ assert_return(m, -EINVAL); - r = message_attribute_has_type(m, type, NLA_CACHE_INFO); + r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_CACHE_INFO); if (r < 0) return r; - r = rtnl_message_read_internal(m, type, &attr_data); + r = netlink_message_read_internal(m, type, &attr_data, NULL); if (r < 0) return r; else if ((size_t)r < sizeof(struct ifa_cacheinfo)) @@ -631,11 +650,11 @@ int sd_netlink_message_read_in_addr(sd_netlink_message *m, unsigned short type, assert_return(m, -EINVAL); - r = message_attribute_has_type(m, type, NLA_IN_ADDR); + r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_IN_ADDR); if (r < 0) return r; - r = rtnl_message_read_internal(m, type, &attr_data); + r = netlink_message_read_internal(m, type, &attr_data, NULL); if (r < 0) return r; else if ((size_t)r < sizeof(struct in_addr)) @@ -653,11 +672,11 @@ int sd_netlink_message_read_in6_addr(sd_netlink_message *m, unsigned short type, assert_return(m, -EINVAL); - r = message_attribute_has_type(m, type, NLA_IN_ADDR); + r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_IN_ADDR); if (r < 0) return r; - r = rtnl_message_read_internal(m, type, &attr_data); + r = netlink_message_read_internal(m, type, &attr_data, NULL); if (r < 0) return r; else if ((size_t)r < sizeof(struct in6_addr)) @@ -669,34 +688,73 @@ int sd_netlink_message_read_in6_addr(sd_netlink_message *m, unsigned short type, return 0; } -int sd_netlink_message_enter_container(sd_netlink_message *m, unsigned short type) { +static int netlink_container_parse(sd_netlink_message *m, + struct netlink_container *container, + int count, + struct rtattr *rta, + unsigned int rt_len) { + _cleanup_free_ struct netlink_attribute *attributes = NULL; + + attributes = new0(struct netlink_attribute, count); + if(!attributes) + return -ENOMEM; + + for (; RTA_OK(rta, rt_len); rta = RTA_NEXT(rta, rt_len)) { + unsigned short type; + + type = RTA_TYPE(rta); + + /* if the kernel is newer than the headers we used + when building, we ignore out-of-range attributes */ + if (type >= count) + continue; + + if (attributes[type].offset) + log_debug("rtnl: message parse - overwriting repeated attribute"); + + attributes[type].offset = (uint8_t *) rta - (uint8_t *) m->hdr; + attributes[type].nested = RTA_FLAGS(rta) & NLA_F_NESTED; + attributes[type].net_byteorder = RTA_FLAGS(rta) & NLA_F_NET_BYTEORDER; + } + + container->attributes = attributes; + attributes = NULL; + container->n_attributes = count; + + return 0; +} + +int sd_netlink_message_enter_container(sd_netlink_message *m, unsigned short type_id) { const NLType *nl_type; const NLTypeSystem *type_system; void *container; + uint16_t type; size_t size; int r; assert_return(m, -EINVAL); assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -EINVAL); - r = type_system_get_type(m->container_type_system[m->n_containers], + r = type_system_get_type(m->containers[m->n_containers].type_system, &nl_type, - type); + type_id); if (r < 0) return r; - if (nl_type->type == NLA_NESTED) { - r = type_system_get_type_system(m->container_type_system[m->n_containers], + type = type_get_type(nl_type); + + if (type == NETLINK_TYPE_NESTED) { + r = type_system_get_type_system(m->containers[m->n_containers].type_system, &type_system, - type); + type_id); if (r < 0) return r; - } else if (nl_type->type == NLA_UNION) { + } else if (type == NETLINK_TYPE_UNION) { const NLTypeSystemUnion *type_system_union; - r = type_system_get_type_system_union(m->container_type_system[m->n_containers], + r = type_system_get_type_system_union(m->containers[m->n_containers].type_system, &type_system_union, - type); + type_id); if (r < 0) return r; @@ -739,7 +797,7 @@ int sd_netlink_message_enter_container(sd_netlink_message *m, unsigned short typ } else return -EINVAL; - r = rtnl_message_read_internal(m, type, &container); + r = netlink_message_read_internal(m, type_id, &container, NULL); if (r < 0) return r; else @@ -747,18 +805,17 @@ int sd_netlink_message_enter_container(sd_netlink_message *m, unsigned short typ m->n_containers ++; - r = rtnl_message_parse(m, - &m->rta_offset_tb[m->n_containers], - &m->rta_tb_size[m->n_containers], - type_system->max, - container, - size); + r = netlink_container_parse(m, + &m->containers[m->n_containers], + type_system_get_count(type_system), + container, + size); if (r < 0) { m->n_containers --; return r; } - m->container_type_system[m->n_containers] = type_system; + m->containers[m->n_containers].type_system = type_system; return 0; } @@ -768,9 +825,9 @@ int sd_netlink_message_exit_container(sd_netlink_message *m) { assert_return(m->sealed, -EINVAL); assert_return(m->n_containers > 0, -EINVAL); - free(m->rta_offset_tb[m->n_containers]); - m->rta_offset_tb[m->n_containers] = NULL; - m->container_type_system[m->n_containers] = NULL; + free(m->containers[m->n_containers].attributes); + m->containers[m->n_containers].attributes = NULL; + m->containers[m->n_containers].type_system = NULL; m->n_containers --; @@ -805,43 +862,10 @@ int sd_netlink_message_get_errno(sd_netlink_message *m) { return err->error; } -int rtnl_message_parse(sd_netlink_message *m, - size_t **rta_offset_tb, - unsigned short *rta_tb_size, - int max, - struct rtattr *rta, - unsigned int rt_len) { - unsigned short type; - size_t *tb; - - tb = new0(size_t, max + 1); - if(!tb) - return -ENOMEM; - - *rta_tb_size = max + 1; - - for (; RTA_OK(rta, rt_len); rta = RTA_NEXT(rta, rt_len)) { - type = RTA_TYPE(rta); - - /* if the kernel is newer than the headers we used - when building, we ignore out-of-range attributes - */ - if (type > max) - continue; - - if (tb[type]) - log_debug("rtnl: message parse - overwriting repeated attribute"); - - tb[type] = (uint8_t *) rta - (uint8_t *) m->hdr; - } - - *rta_offset_tb = tb; - - return 0; -} - int sd_netlink_message_rewind(sd_netlink_message *m) { - const NLType *type; + const NLType *nl_type; + uint16_t type; + size_t size; unsigned i; int r; @@ -852,39 +876,38 @@ int sd_netlink_message_rewind(sd_netlink_message *m) { rtnl_message_seal(m); for (i = 1; i <= m->n_containers; i++) { - free(m->rta_offset_tb[i]); - m->rta_offset_tb[i] = NULL; - m->rta_tb_size[i] = 0; - m->container_type_system[i] = NULL; + free(m->containers[i].attributes); + m->containers[i].attributes = NULL; } m->n_containers = 0; - if (m->rta_offset_tb[0]) { + if (m->containers[0].attributes) { /* top-level attributes have already been parsed */ return 0; } assert(m->hdr); - r = type_system_get_type(NULL, &type, m->hdr->nlmsg_type); + r = type_system_get_type(&type_system_root, &nl_type, m->hdr->nlmsg_type); if (r < 0) return r; - if (type->type == NLA_NESTED) { - const NLTypeSystem *type_system = type->type_system; + type = type_get_type(nl_type); + size = type_get_size(nl_type); + + if (type == NETLINK_TYPE_NESTED) { + const NLTypeSystem *type_system; - assert(type_system); + type_get_type_system(nl_type, &type_system); - m->container_type_system[0] = type_system; + m->containers[0].type_system = type_system; - r = rtnl_message_parse(m, - &m->rta_offset_tb[m->n_containers], - &m->rta_tb_size[m->n_containers], - type_system->max, - (struct rtattr*)((uint8_t*)NLMSG_DATA(m->hdr) + - NLMSG_ALIGN(type->size)), - NLMSG_PAYLOAD(m->hdr, type->size)); + r = netlink_container_parse(m, + &m->containers[m->n_containers], + type_system_get_count(type_system), + (struct rtattr*)((uint8_t*)NLMSG_DATA(m->hdr) + NLMSG_ALIGN(size)), + NLMSG_PAYLOAD(m->hdr, size)); if (r < 0) return r; } diff --git a/src/libsystemd/sd-netlink/netlink-socket.c b/src/libsystemd/sd-netlink/netlink-socket.c index 8136cf36ae..84ff7c38c9 100644 --- a/src/libsystemd/sd-netlink/netlink-socket.c +++ b/src/libsystemd/sd-netlink/netlink-socket.c @@ -243,7 +243,7 @@ int socket_read_message(sd_netlink *rtnl) { } /* check that we support this message type */ - r = type_system_get_type(NULL, &nl_type, new_msg->nlmsg_type); + r = type_system_get_type(&type_system_root, &nl_type, new_msg->nlmsg_type); if (r < 0) { if (r == -EOPNOTSUPP) log_debug("sd-netlink: ignored message with unknown type: %i", @@ -253,7 +253,7 @@ int socket_read_message(sd_netlink *rtnl) { } /* check that the size matches the message type */ - if (new_msg->nlmsg_len < NLMSG_LENGTH(nl_type->size)) { + if (new_msg->nlmsg_len < NLMSG_LENGTH(type_get_size(nl_type))) { log_debug("sd-netlink: message larger than expected, dropping"); continue; } diff --git a/src/libsystemd/sd-netlink/netlink-types.c b/src/libsystemd/sd-netlink/netlink-types.c index 273033770f..9b68935245 100644 --- a/src/libsystemd/sd-netlink/netlink-types.c +++ b/src/libsystemd/sd-netlink/netlink-types.c @@ -39,152 +39,205 @@ #include "netlink-types.h" #include "missing.h" +/* Maximum ARP IP target defined in kernel */ +#define BOND_MAX_ARP_TARGETS 16 + +typedef enum { + BOND_ARP_TARGETS_0, + BOND_ARP_TARGETS_1, + BOND_ARP_TARGETS_2, + BOND_ARP_TARGETS_3, + BOND_ARP_TARGETS_4, + BOND_ARP_TARGETS_5, + BOND_ARP_TARGETS_6, + BOND_ARP_TARGETS_7, + BOND_ARP_TARGETS_8, + BOND_ARP_TARGETS_9, + BOND_ARP_TARGETS_10, + BOND_ARP_TARGETS_11, + BOND_ARP_TARGETS_12, + BOND_ARP_TARGETS_13, + BOND_ARP_TARGETS_14, + BOND_ARP_TARGETS_MAX = BOND_MAX_ARP_TARGETS, +} BondArpTargets; + +struct NLType { + uint16_t type; + size_t size; + const NLTypeSystem *type_system; + const NLTypeSystemUnion *type_system_union; +}; + +struct NLTypeSystem { + uint16_t count; + const NLType *types; +}; + static const NLTypeSystem rtnl_link_type_system; +static const NLType empty_types[1] = { + /* fake array to avoid .types==NULL, which denotes invalid type-systems */ +}; + +static const NLTypeSystem empty_type_system = { + .count = 0, + .types = empty_types, +}; + static const NLType rtnl_link_info_data_veth_types[VETH_INFO_MAX + 1] = { - [VETH_INFO_PEER] = { .type = NLA_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) }, + [VETH_INFO_PEER] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) }, }; static const NLType rtnl_link_info_data_ipvlan_types[IFLA_IPVLAN_MAX + 1] = { - [IFLA_IPVLAN_MODE] = { .type = NLA_U16 }, + [IFLA_IPVLAN_MODE] = { .type = NETLINK_TYPE_U16 }, }; static const NLType rtnl_link_info_data_macvlan_types[IFLA_MACVLAN_MAX + 1] = { - [IFLA_MACVLAN_MODE] = { .type = NLA_U32 }, - [IFLA_MACVLAN_FLAGS] = { .type = NLA_U16 }, + [IFLA_MACVLAN_MODE] = { .type = NETLINK_TYPE_U32 }, + [IFLA_MACVLAN_FLAGS] = { .type = NETLINK_TYPE_U16 }, }; static const NLType rtnl_link_info_data_bridge_types[IFLA_BRIDGE_MAX + 1] = { - [IFLA_BRIDGE_FLAGS] = { .type = NLA_U16 }, - [IFLA_BRIDGE_MODE] = { .type = NLA_U16 }, + [IFLA_BRIDGE_FLAGS] = { .type = NETLINK_TYPE_U16 }, + [IFLA_BRIDGE_MODE] = { .type = NETLINK_TYPE_U16 }, /* - [IFLA_BRIDGE_VLAN_INFO] = { .type = NLA_BINARY, + [IFLA_BRIDGE_VLAN_INFO] = { .type = NETLINK_TYPE_BINARY, .len = sizeof(struct bridge_vlan_info), }, */ }; static const NLType rtnl_link_info_data_vlan_types[IFLA_VLAN_MAX + 1] = { - [IFLA_VLAN_ID] = { .type = NLA_U16 }, + [IFLA_VLAN_ID] = { .type = NETLINK_TYPE_U16 }, /* [IFLA_VLAN_FLAGS] = { .len = sizeof(struct ifla_vlan_flags) }, - [IFLA_VLAN_EGRESS_QOS] = { .type = NLA_NESTED }, - [IFLA_VLAN_INGRESS_QOS] = { .type = NLA_NESTED }, + [IFLA_VLAN_EGRESS_QOS] = { .type = NETLINK_TYPE_NESTED }, + [IFLA_VLAN_INGRESS_QOS] = { .type = NETLINK_TYPE_NESTED }, */ - [IFLA_VLAN_PROTOCOL] = { .type = NLA_U16 }, + [IFLA_VLAN_PROTOCOL] = { .type = NETLINK_TYPE_U16 }, }; static const NLType rtnl_link_info_data_vxlan_types[IFLA_VXLAN_MAX+1] = { - [IFLA_VXLAN_ID] = { .type = NLA_U32 }, - [IFLA_VXLAN_GROUP] = {.type = NLA_IN_ADDR }, - [IFLA_VXLAN_LINK] = { .type = NLA_U32 }, - [IFLA_VXLAN_LOCAL] = { .type = NLA_U32}, - [IFLA_VXLAN_TTL] = { .type = NLA_U8 }, - [IFLA_VXLAN_TOS] = { .type = NLA_U8 }, - [IFLA_VXLAN_LEARNING] = { .type = NLA_U8 }, - [IFLA_VXLAN_AGEING] = { .type = NLA_U32 }, - [IFLA_VXLAN_LIMIT] = { .type = NLA_U32 }, - [IFLA_VXLAN_PORT_RANGE] = { .type = NLA_U32}, - [IFLA_VXLAN_PROXY] = { .type = NLA_U8 }, - [IFLA_VXLAN_RSC] = { .type = NLA_U8 }, - [IFLA_VXLAN_L2MISS] = { .type = NLA_U8 }, - [IFLA_VXLAN_L3MISS] = { .type = NLA_U8 }, + [IFLA_VXLAN_ID] = { .type = NETLINK_TYPE_U32 }, + [IFLA_VXLAN_GROUP] = { .type = NETLINK_TYPE_IN_ADDR }, + [IFLA_VXLAN_LINK] = { .type = NETLINK_TYPE_U32 }, + [IFLA_VXLAN_LOCAL] = { .type = NETLINK_TYPE_U32}, + [IFLA_VXLAN_TTL] = { .type = NETLINK_TYPE_U8 }, + [IFLA_VXLAN_TOS] = { .type = NETLINK_TYPE_U8 }, + [IFLA_VXLAN_LEARNING] = { .type = NETLINK_TYPE_U8 }, + [IFLA_VXLAN_AGEING] = { .type = NETLINK_TYPE_U32 }, + [IFLA_VXLAN_LIMIT] = { .type = NETLINK_TYPE_U32 }, + [IFLA_VXLAN_PORT_RANGE] = { .type = NETLINK_TYPE_U32}, + [IFLA_VXLAN_PROXY] = { .type = NETLINK_TYPE_U8 }, + [IFLA_VXLAN_RSC] = { .type = NETLINK_TYPE_U8 }, + [IFLA_VXLAN_L2MISS] = { .type = NETLINK_TYPE_U8 }, + [IFLA_VXLAN_L3MISS] = { .type = NETLINK_TYPE_U8 }, }; static const NLType rtnl_bond_arp_target_types[BOND_ARP_TARGETS_MAX + 1] = { - [BOND_ARP_TARGETS_0] = { .type = NLA_U32 }, - [BOND_ARP_TARGETS_1] = { .type = NLA_U32 }, - [BOND_ARP_TARGETS_2] = { .type = NLA_U32 }, - [BOND_ARP_TARGETS_3] = { .type = NLA_U32 }, - [BOND_ARP_TARGETS_4] = { .type = NLA_U32 }, - [BOND_ARP_TARGETS_5] = { .type = NLA_U32 }, - [BOND_ARP_TARGETS_6] = { .type = NLA_U32 }, - [BOND_ARP_TARGETS_7] = { .type = NLA_U32 }, - [BOND_ARP_TARGETS_8] = { .type = NLA_U32 }, - [BOND_ARP_TARGETS_9] = { .type = NLA_U32 }, - [BOND_ARP_TARGETS_10] = { .type = NLA_U32 }, - [BOND_ARP_TARGETS_11] = { .type = NLA_U32 }, - [BOND_ARP_TARGETS_12] = { .type = NLA_U32 }, - [BOND_ARP_TARGETS_13] = { .type = NLA_U32 }, - [BOND_ARP_TARGETS_14] = { .type = NLA_U32 }, - [BOND_ARP_TARGETS_MAX] = { .type = NLA_U32 }, + [BOND_ARP_TARGETS_0] = { .type = NETLINK_TYPE_U32 }, + [BOND_ARP_TARGETS_1] = { .type = NETLINK_TYPE_U32 }, + [BOND_ARP_TARGETS_2] = { .type = NETLINK_TYPE_U32 }, + [BOND_ARP_TARGETS_3] = { .type = NETLINK_TYPE_U32 }, + [BOND_ARP_TARGETS_4] = { .type = NETLINK_TYPE_U32 }, + [BOND_ARP_TARGETS_5] = { .type = NETLINK_TYPE_U32 }, + [BOND_ARP_TARGETS_6] = { .type = NETLINK_TYPE_U32 }, + [BOND_ARP_TARGETS_7] = { .type = NETLINK_TYPE_U32 }, + [BOND_ARP_TARGETS_8] = { .type = NETLINK_TYPE_U32 }, + [BOND_ARP_TARGETS_9] = { .type = NETLINK_TYPE_U32 }, + [BOND_ARP_TARGETS_10] = { .type = NETLINK_TYPE_U32 }, + [BOND_ARP_TARGETS_11] = { .type = NETLINK_TYPE_U32 }, + [BOND_ARP_TARGETS_12] = { .type = NETLINK_TYPE_U32 }, + [BOND_ARP_TARGETS_13] = { .type = NETLINK_TYPE_U32 }, + [BOND_ARP_TARGETS_14] = { .type = NETLINK_TYPE_U32 }, + [BOND_ARP_TARGETS_MAX] = { .type = NETLINK_TYPE_U32 }, }; static const NLTypeSystem rtnl_bond_arp_type_system = { - .max = ELEMENTSOF(rtnl_bond_arp_target_types) - 1, + .count = ELEMENTSOF(rtnl_bond_arp_target_types), .types = rtnl_bond_arp_target_types, }; static const NLType rtnl_link_info_data_bond_types[IFLA_BOND_MAX + 1] = { - [IFLA_BOND_MODE] = { .type = NLA_U8 }, - [IFLA_BOND_ACTIVE_SLAVE] = { .type = NLA_U32 }, - [IFLA_BOND_MIIMON] = { .type = NLA_U32 }, - [IFLA_BOND_UPDELAY] = { .type = NLA_U32 }, - [IFLA_BOND_DOWNDELAY] = { .type = NLA_U32 }, - [IFLA_BOND_USE_CARRIER] = { .type = NLA_U8 }, - [IFLA_BOND_ARP_INTERVAL] = { .type = NLA_U32 }, - [IFLA_BOND_ARP_IP_TARGET] = { .type = NLA_NESTED, .type_system = &rtnl_bond_arp_type_system }, - [IFLA_BOND_ARP_VALIDATE] = { .type = NLA_U32 }, - [IFLA_BOND_ARP_ALL_TARGETS] = { .type = NLA_U32 }, - [IFLA_BOND_PRIMARY] = { .type = NLA_U32 }, - [IFLA_BOND_PRIMARY_RESELECT] = { .type = NLA_U8 }, - [IFLA_BOND_FAIL_OVER_MAC] = { .type = NLA_U8 }, - [IFLA_BOND_XMIT_HASH_POLICY] = { .type = NLA_U8 }, - [IFLA_BOND_RESEND_IGMP] = { .type = NLA_U32 }, - [IFLA_BOND_NUM_PEER_NOTIF] = { .type = NLA_U8 }, - [IFLA_BOND_ALL_SLAVES_ACTIVE] = { .type = NLA_U8 }, - [IFLA_BOND_MIN_LINKS] = { .type = NLA_U32 }, - [IFLA_BOND_LP_INTERVAL] = { .type = NLA_U32 }, - [IFLA_BOND_PACKETS_PER_SLAVE] = { .type = NLA_U32 }, - [IFLA_BOND_AD_LACP_RATE] = { .type = NLA_U8 }, - [IFLA_BOND_AD_SELECT] = { .type = NLA_U8 }, - [IFLA_BOND_AD_INFO] = { .type = NLA_NESTED }, + [IFLA_BOND_MODE] = { .type = NETLINK_TYPE_U8 }, + [IFLA_BOND_ACTIVE_SLAVE] = { .type = NETLINK_TYPE_U32 }, + [IFLA_BOND_MIIMON] = { .type = NETLINK_TYPE_U32 }, + [IFLA_BOND_UPDELAY] = { .type = NETLINK_TYPE_U32 }, + [IFLA_BOND_DOWNDELAY] = { .type = NETLINK_TYPE_U32 }, + [IFLA_BOND_USE_CARRIER] = { .type = NETLINK_TYPE_U8 }, + [IFLA_BOND_ARP_INTERVAL] = { .type = NETLINK_TYPE_U32 }, + [IFLA_BOND_ARP_IP_TARGET] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_bond_arp_type_system }, + [IFLA_BOND_ARP_VALIDATE] = { .type = NETLINK_TYPE_U32 }, + [IFLA_BOND_ARP_ALL_TARGETS] = { .type = NETLINK_TYPE_U32 }, + [IFLA_BOND_PRIMARY] = { .type = NETLINK_TYPE_U32 }, + [IFLA_BOND_PRIMARY_RESELECT] = { .type = NETLINK_TYPE_U8 }, + [IFLA_BOND_FAIL_OVER_MAC] = { .type = NETLINK_TYPE_U8 }, + [IFLA_BOND_XMIT_HASH_POLICY] = { .type = NETLINK_TYPE_U8 }, + [IFLA_BOND_RESEND_IGMP] = { .type = NETLINK_TYPE_U32 }, + [IFLA_BOND_NUM_PEER_NOTIF] = { .type = NETLINK_TYPE_U8 }, + [IFLA_BOND_ALL_SLAVES_ACTIVE] = { .type = NETLINK_TYPE_U8 }, + [IFLA_BOND_MIN_LINKS] = { .type = NETLINK_TYPE_U32 }, + [IFLA_BOND_LP_INTERVAL] = { .type = NETLINK_TYPE_U32 }, + [IFLA_BOND_PACKETS_PER_SLAVE] = { .type = NETLINK_TYPE_U32 }, + [IFLA_BOND_AD_LACP_RATE] = { .type = NETLINK_TYPE_U8 }, + [IFLA_BOND_AD_SELECT] = { .type = NETLINK_TYPE_U8 }, + [IFLA_BOND_AD_INFO] = { .type = NETLINK_TYPE_NESTED }, }; static const NLType rtnl_link_info_data_iptun_types[IFLA_IPTUN_MAX + 1] = { - [IFLA_IPTUN_LINK] = { .type = NLA_U32 }, - [IFLA_IPTUN_LOCAL] = { .type = NLA_IN_ADDR }, - [IFLA_IPTUN_REMOTE] = { .type = NLA_IN_ADDR }, - [IFLA_IPTUN_TTL] = { .type = NLA_U8 }, - [IFLA_IPTUN_TOS] = { .type = NLA_U8 }, - [IFLA_IPTUN_PMTUDISC] = { .type = NLA_U8 }, - [IFLA_IPTUN_FLAGS] = { .type = NLA_U16 }, - [IFLA_IPTUN_PROTO] = { .type = NLA_U8 }, - [IFLA_IPTUN_6RD_PREFIX] = { .type = NLA_IN_ADDR }, - [IFLA_IPTUN_6RD_RELAY_PREFIX] = { .type = NLA_U32 }, - [IFLA_IPTUN_6RD_PREFIXLEN] = { .type = NLA_U16 }, - [IFLA_IPTUN_6RD_RELAY_PREFIXLEN] = { .type = NLA_U16 }, + [IFLA_IPTUN_LINK] = { .type = NETLINK_TYPE_U32 }, + [IFLA_IPTUN_LOCAL] = { .type = NETLINK_TYPE_IN_ADDR }, + [IFLA_IPTUN_REMOTE] = { .type = NETLINK_TYPE_IN_ADDR }, + [IFLA_IPTUN_TTL] = { .type = NETLINK_TYPE_U8 }, + [IFLA_IPTUN_TOS] = { .type = NETLINK_TYPE_U8 }, + [IFLA_IPTUN_PMTUDISC] = { .type = NETLINK_TYPE_U8 }, + [IFLA_IPTUN_FLAGS] = { .type = NETLINK_TYPE_U16 }, + [IFLA_IPTUN_PROTO] = { .type = NETLINK_TYPE_U8 }, + [IFLA_IPTUN_6RD_PREFIX] = { .type = NETLINK_TYPE_IN_ADDR }, + [IFLA_IPTUN_6RD_RELAY_PREFIX] = { .type = NETLINK_TYPE_U32 }, + [IFLA_IPTUN_6RD_PREFIXLEN] = { .type = NETLINK_TYPE_U16 }, + [IFLA_IPTUN_6RD_RELAY_PREFIXLEN] = { .type = NETLINK_TYPE_U16 }, + [IFLA_IPTUN_ENCAP_TYPE] = { .type = NETLINK_TYPE_U16 }, + [IFLA_IPTUN_ENCAP_FLAGS] = { .type = NETLINK_TYPE_U16 }, + [IFLA_IPTUN_ENCAP_SPORT] = { .type = NETLINK_TYPE_U16 }, + [IFLA_IPTUN_ENCAP_DPORT] = { .type = NETLINK_TYPE_U16 }, }; static const NLType rtnl_link_info_data_ipgre_types[IFLA_GRE_MAX + 1] = { - [IFLA_GRE_LINK] = { .type = NLA_U32 }, - [IFLA_GRE_IFLAGS] = { .type = NLA_U16 }, - [IFLA_GRE_OFLAGS] = { .type = NLA_U16 }, - [IFLA_GRE_IKEY] = { .type = NLA_U32 }, - [IFLA_GRE_OKEY] = { .type = NLA_U32 }, - [IFLA_GRE_LOCAL] = { .type = NLA_IN_ADDR }, - [IFLA_GRE_REMOTE] = { .type = NLA_IN_ADDR }, - [IFLA_GRE_TTL] = { .type = NLA_U8 }, - [IFLA_GRE_TOS] = { .type = NLA_U8 }, - [IFLA_GRE_PMTUDISC] = { .type = NLA_U8 }, + [IFLA_GRE_LINK] = { .type = NETLINK_TYPE_U32 }, + [IFLA_GRE_IFLAGS] = { .type = NETLINK_TYPE_U16 }, + [IFLA_GRE_OFLAGS] = { .type = NETLINK_TYPE_U16 }, + [IFLA_GRE_IKEY] = { .type = NETLINK_TYPE_U32 }, + [IFLA_GRE_OKEY] = { .type = NETLINK_TYPE_U32 }, + [IFLA_GRE_LOCAL] = { .type = NETLINK_TYPE_IN_ADDR }, + [IFLA_GRE_REMOTE] = { .type = NETLINK_TYPE_IN_ADDR }, + [IFLA_GRE_TTL] = { .type = NETLINK_TYPE_U8 }, + [IFLA_GRE_TOS] = { .type = NETLINK_TYPE_U8 }, + [IFLA_GRE_PMTUDISC] = { .type = NETLINK_TYPE_U8 }, + [IFLA_GRE_FLOWINFO] = { .type = NETLINK_TYPE_U32 }, + [IFLA_GRE_FLAGS] = { .type = NETLINK_TYPE_U32 }, + [IFLA_GRE_ENCAP_TYPE] = { .type = NETLINK_TYPE_U16 }, + [IFLA_GRE_ENCAP_FLAGS] = { .type = NETLINK_TYPE_U16 }, + [IFLA_GRE_ENCAP_SPORT] = { .type = NETLINK_TYPE_U16 }, + [IFLA_GRE_ENCAP_DPORT] = { .type = NETLINK_TYPE_U16 }, }; static const NLType rtnl_link_info_data_ipvti_types[IFLA_VTI_MAX + 1] = { - [IFLA_VTI_LINK] = { .type = NLA_U32 }, - [IFLA_VTI_IKEY] = { .type = NLA_U32 }, - [IFLA_VTI_OKEY] = { .type = NLA_U32 }, - [IFLA_VTI_LOCAL] = { .type = NLA_IN_ADDR }, - [IFLA_VTI_REMOTE] = { .type = NLA_IN_ADDR }, + [IFLA_VTI_LINK] = { .type = NETLINK_TYPE_U32 }, + [IFLA_VTI_IKEY] = { .type = NETLINK_TYPE_U32 }, + [IFLA_VTI_OKEY] = { .type = NETLINK_TYPE_U32 }, + [IFLA_VTI_LOCAL] = { .type = NETLINK_TYPE_IN_ADDR }, + [IFLA_VTI_REMOTE] = { .type = NETLINK_TYPE_IN_ADDR }, }; static const NLType rtnl_link_info_data_ip6tnl_types[IFLA_IPTUN_MAX + 1] = { - [IFLA_IPTUN_LINK] = { .type = NLA_U32 }, - [IFLA_IPTUN_LOCAL] = { .type = NLA_IN_ADDR }, - [IFLA_IPTUN_REMOTE] = { .type = NLA_IN_ADDR }, - [IFLA_IPTUN_TTL] = { .type = NLA_U8 }, - [IFLA_IPTUN_FLAGS] = { .type = NLA_U32 }, - [IFLA_IPTUN_PROTO] = { .type = NLA_U8 }, - [IFLA_IPTUN_ENCAP_LIMIT] = { .type = NLA_U8 }, - [IFLA_IPTUN_FLOWINFO] = { .type = NLA_U32}, + [IFLA_IPTUN_LINK] = { .type = NETLINK_TYPE_U32 }, + [IFLA_IPTUN_LOCAL] = { .type = NETLINK_TYPE_IN_ADDR }, + [IFLA_IPTUN_REMOTE] = { .type = NETLINK_TYPE_IN_ADDR }, + [IFLA_IPTUN_TTL] = { .type = NETLINK_TYPE_U8 }, + [IFLA_IPTUN_FLAGS] = { .type = NETLINK_TYPE_U32 }, + [IFLA_IPTUN_PROTO] = { .type = NETLINK_TYPE_U8 }, + [IFLA_IPTUN_ENCAP_LIMIT] = { .type = NETLINK_TYPE_U8 }, + [IFLA_IPTUN_FLOWINFO] = { .type = NETLINK_TYPE_U32 }, }; /* these strings must match the .kind entries in the kernel */ @@ -211,37 +264,37 @@ static const char* const nl_union_link_info_data_table[_NL_UNION_LINK_INFO_DATA_ DEFINE_STRING_TABLE_LOOKUP(nl_union_link_info_data, NLUnionLinkInfoData); static const NLTypeSystem rtnl_link_info_data_type_systems[_NL_UNION_LINK_INFO_DATA_MAX] = { - [NL_UNION_LINK_INFO_DATA_BOND] = { .max = ELEMENTSOF(rtnl_link_info_data_bond_types) - 1, + [NL_UNION_LINK_INFO_DATA_BOND] = { .count = ELEMENTSOF(rtnl_link_info_data_bond_types), .types = rtnl_link_info_data_bond_types }, - [NL_UNION_LINK_INFO_DATA_BRIDGE] = { .max = ELEMENTSOF(rtnl_link_info_data_bridge_types) - 1, + [NL_UNION_LINK_INFO_DATA_BRIDGE] = { .count = ELEMENTSOF(rtnl_link_info_data_bridge_types), .types = rtnl_link_info_data_bridge_types }, - [NL_UNION_LINK_INFO_DATA_VLAN] = { .max = ELEMENTSOF(rtnl_link_info_data_vlan_types) - 1, + [NL_UNION_LINK_INFO_DATA_VLAN] = { .count = ELEMENTSOF(rtnl_link_info_data_vlan_types), .types = rtnl_link_info_data_vlan_types }, - [NL_UNION_LINK_INFO_DATA_VETH] = { .max = ELEMENTSOF(rtnl_link_info_data_veth_types) - 1, + [NL_UNION_LINK_INFO_DATA_VETH] = { .count = ELEMENTSOF(rtnl_link_info_data_veth_types), .types = rtnl_link_info_data_veth_types }, - [NL_UNION_LINK_INFO_DATA_MACVLAN] = { .max = ELEMENTSOF(rtnl_link_info_data_macvlan_types) - 1, + [NL_UNION_LINK_INFO_DATA_MACVLAN] = { .count = ELEMENTSOF(rtnl_link_info_data_macvlan_types), .types = rtnl_link_info_data_macvlan_types }, - [NL_UNION_LINK_INFO_DATA_IPVLAN] = { .max = ELEMENTSOF(rtnl_link_info_data_ipvlan_types) - 1, + [NL_UNION_LINK_INFO_DATA_IPVLAN] = { .count = ELEMENTSOF(rtnl_link_info_data_ipvlan_types), .types = rtnl_link_info_data_ipvlan_types }, - [NL_UNION_LINK_INFO_DATA_VXLAN] = { .max = ELEMENTSOF(rtnl_link_info_data_vxlan_types) - 1, + [NL_UNION_LINK_INFO_DATA_VXLAN] = { .count = ELEMENTSOF(rtnl_link_info_data_vxlan_types), .types = rtnl_link_info_data_vxlan_types }, - [NL_UNION_LINK_INFO_DATA_IPIP_TUNNEL] = { .max = ELEMENTSOF(rtnl_link_info_data_iptun_types) - 1, + [NL_UNION_LINK_INFO_DATA_IPIP_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_iptun_types), .types = rtnl_link_info_data_iptun_types }, - [NL_UNION_LINK_INFO_DATA_IPGRE_TUNNEL] = { .max = ELEMENTSOF(rtnl_link_info_data_ipgre_types) - 1, + [NL_UNION_LINK_INFO_DATA_IPGRE_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipgre_types), .types = rtnl_link_info_data_ipgre_types }, - [NL_UNION_LINK_INFO_DATA_IPGRETAP_TUNNEL] = { .max = ELEMENTSOF(rtnl_link_info_data_ipgre_types) - 1, + [NL_UNION_LINK_INFO_DATA_IPGRETAP_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipgre_types), .types = rtnl_link_info_data_ipgre_types }, - [NL_UNION_LINK_INFO_DATA_IP6GRE_TUNNEL] = { .max = ELEMENTSOF(rtnl_link_info_data_ipgre_types) - 1, + [NL_UNION_LINK_INFO_DATA_IP6GRE_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipgre_types), .types = rtnl_link_info_data_ipgre_types }, - [NL_UNION_LINK_INFO_DATA_IP6GRETAP_TUNNEL] = { .max = ELEMENTSOF(rtnl_link_info_data_ipgre_types) - 1, + [NL_UNION_LINK_INFO_DATA_IP6GRETAP_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipgre_types), .types = rtnl_link_info_data_ipgre_types }, - [NL_UNION_LINK_INFO_DATA_SIT_TUNNEL] = { .max = ELEMENTSOF(rtnl_link_info_data_iptun_types) - 1, + [NL_UNION_LINK_INFO_DATA_SIT_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_iptun_types), .types = rtnl_link_info_data_iptun_types }, - [NL_UNION_LINK_INFO_DATA_VTI_TUNNEL] = { .max = ELEMENTSOF(rtnl_link_info_data_ipvti_types) - 1, + [NL_UNION_LINK_INFO_DATA_VTI_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipvti_types), .types = rtnl_link_info_data_ipvti_types }, - [NL_UNION_LINK_INFO_DATA_VTI6_TUNNEL] = { .max = ELEMENTSOF(rtnl_link_info_data_ipvti_types) - 1, + [NL_UNION_LINK_INFO_DATA_VTI6_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipvti_types), .types = rtnl_link_info_data_ipvti_types }, - [NL_UNION_LINK_INFO_DATA_IP6TNL_TUNNEL] = { .max = ELEMENTSOF(rtnl_link_info_data_ip6tnl_types) - 1, + [NL_UNION_LINK_INFO_DATA_IP6TNL_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ip6tnl_types), .types = rtnl_link_info_data_ip6tnl_types }, }; @@ -255,33 +308,36 @@ static const NLTypeSystemUnion rtnl_link_info_data_type_system_union = { }; static const NLType rtnl_link_info_types[IFLA_INFO_MAX + 1] = { - [IFLA_INFO_KIND] = { .type = NLA_STRING }, - [IFLA_INFO_DATA] = { .type = NLA_UNION, .type_system_union = &rtnl_link_info_data_type_system_union}, + [IFLA_INFO_KIND] = { .type = NETLINK_TYPE_STRING }, + [IFLA_INFO_DATA] = { .type = NETLINK_TYPE_UNION, .type_system_union = &rtnl_link_info_data_type_system_union}, /* [IFLA_INFO_XSTATS], - [IFLA_INFO_SLAVE_KIND] = { .type = NLA_STRING }, - [IFLA_INFO_SLAVE_DATA] = { .type = NLA_NESTED }, + [IFLA_INFO_SLAVE_KIND] = { .type = NETLINK_TYPE_STRING }, + [IFLA_INFO_SLAVE_DATA] = { .type = NETLINK_TYPE_NESTED }, */ }; static const NLTypeSystem rtnl_link_info_type_system = { - .max = ELEMENTSOF(rtnl_link_info_types) - 1, + .count = ELEMENTSOF(rtnl_link_info_types), .types = rtnl_link_info_types, }; static const struct NLType rtnl_prot_info_bridge_port_types[IFLA_BRPORT_MAX + 1] = { - [IFLA_BRPORT_STATE] = { .type = NLA_U8 }, - [IFLA_BRPORT_COST] = { .type = NLA_U32 }, - [IFLA_BRPORT_PRIORITY] = { .type = NLA_U16 }, - [IFLA_BRPORT_MODE] = { .type = NLA_U8 }, - [IFLA_BRPORT_GUARD] = { .type = NLA_U8 }, - [IFLA_BRPORT_PROTECT] = { .type = NLA_U8 }, - [IFLA_BRPORT_LEARNING] = { .type = NLA_U8 }, - [IFLA_BRPORT_UNICAST_FLOOD] = { .type = NLA_U8 }, + [IFLA_BRPORT_STATE] = { .type = NETLINK_TYPE_U8 }, + [IFLA_BRPORT_COST] = { .type = NETLINK_TYPE_U32 }, + [IFLA_BRPORT_PRIORITY] = { .type = NETLINK_TYPE_U16 }, + [IFLA_BRPORT_MODE] = { .type = NETLINK_TYPE_U8 }, + [IFLA_BRPORT_GUARD] = { .type = NETLINK_TYPE_U8 }, + [IFLA_BRPORT_PROTECT] = { .type = NETLINK_TYPE_U8 }, + [IFLA_BRPORT_FAST_LEAVE] = { .type = NETLINK_TYPE_U8 }, + [IFLA_BRPORT_LEARNING] = { .type = NETLINK_TYPE_U8 }, + [IFLA_BRPORT_UNICAST_FLOOD] = { .type = NETLINK_TYPE_U8 }, + [IFLA_BRPORT_PROXYARP] = { .type = NETLINK_TYPE_U8 }, + [IFLA_BRPORT_LEARNING_SYNC] = { .type = NETLINK_TYPE_U8 }, }; static const NLTypeSystem rtnl_prot_info_type_systems[AF_MAX] = { - [AF_BRIDGE] = { .max = ELEMENTSOF(rtnl_prot_info_bridge_port_types) - 1, + [AF_BRIDGE] = { .count = ELEMENTSOF(rtnl_prot_info_bridge_port_types), .types = rtnl_prot_info_bridge_port_types }, }; @@ -292,7 +348,7 @@ static const NLTypeSystemUnion rtnl_prot_info_type_system_union = { }; static const struct NLType rtnl_af_spec_inet6_types[IFLA_INET6_MAX + 1] = { - [IFLA_INET6_FLAGS] = { .type = NLA_U32 }, + [IFLA_INET6_FLAGS] = { .type = NETLINK_TYPE_U32 }, /* IFLA_INET6_CONF, IFLA_INET6_STATS, @@ -300,114 +356,114 @@ static const struct NLType rtnl_af_spec_inet6_types[IFLA_INET6_MAX + 1] = { IFLA_INET6_CACHEINFO, IFLA_INET6_ICMP6STATS, */ - [IFLA_INET6_TOKEN] = { .type = NLA_IN_ADDR }, - [IFLA_INET6_ADDR_GEN_MODE] = { .type = NLA_U8 }, + [IFLA_INET6_TOKEN] = { .type = NETLINK_TYPE_IN_ADDR }, + [IFLA_INET6_ADDR_GEN_MODE] = { .type = NETLINK_TYPE_U8 }, }; static const NLTypeSystem rtnl_af_spec_inet6_type_system = { - .max = ELEMENTSOF(rtnl_af_spec_inet6_types) - 1, + .count = ELEMENTSOF(rtnl_af_spec_inet6_types), .types = rtnl_af_spec_inet6_types, }; static const NLType rtnl_af_spec_types[AF_MAX + 1] = { - [AF_INET6] = { .type = NLA_NESTED, .type_system = &rtnl_af_spec_inet6_type_system }, + [AF_INET6] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_af_spec_inet6_type_system }, }; static const NLTypeSystem rtnl_af_spec_type_system = { - .max = ELEMENTSOF(rtnl_af_spec_types) - 1, + .count = ELEMENTSOF(rtnl_af_spec_types), .types = rtnl_af_spec_types, }; static const NLType rtnl_link_types[IFLA_MAX + 1 ] = { - [IFLA_ADDRESS] = { .type = NLA_ETHER_ADDR, }, - [IFLA_BROADCAST] = { .type = NLA_ETHER_ADDR, }, - [IFLA_IFNAME] = { .type = NLA_STRING, .size = IFNAMSIZ - 1, }, - [IFLA_MTU] = { .type = NLA_U32 }, - [IFLA_LINK] = { .type = NLA_U32 }, + [IFLA_ADDRESS] = { .type = NETLINK_TYPE_ETHER_ADDR }, + [IFLA_BROADCAST] = { .type = NETLINK_TYPE_ETHER_ADDR }, + [IFLA_IFNAME] = { .type = NETLINK_TYPE_STRING, .size = IFNAMSIZ - 1 }, + [IFLA_MTU] = { .type = NETLINK_TYPE_U32 }, + [IFLA_LINK] = { .type = NETLINK_TYPE_U32 }, /* [IFLA_QDISC], [IFLA_STATS], [IFLA_COST], [IFLA_PRIORITY], */ - [IFLA_MASTER] = { .type = NLA_U32 }, + [IFLA_MASTER] = { .type = NETLINK_TYPE_U32 }, /* [IFLA_WIRELESS], */ - [IFLA_PROTINFO] = { .type = NLA_UNION, .type_system_union = &rtnl_prot_info_type_system_union }, - [IFLA_TXQLEN] = { .type = NLA_U32 }, + [IFLA_PROTINFO] = { .type = NETLINK_TYPE_UNION, .type_system_union = &rtnl_prot_info_type_system_union }, + [IFLA_TXQLEN] = { .type = NETLINK_TYPE_U32 }, /* [IFLA_MAP] = { .len = sizeof(struct rtnl_link_ifmap) }, */ - [IFLA_WEIGHT] = { .type = NLA_U32 }, - [IFLA_OPERSTATE] = { .type = NLA_U8 }, - [IFLA_LINKMODE] = { .type = NLA_U8 }, - [IFLA_LINKINFO] = { .type = NLA_NESTED, .type_system = &rtnl_link_info_type_system }, - [IFLA_NET_NS_PID] = { .type = NLA_U32 }, - [IFLA_IFALIAS] = { .type = NLA_STRING, .size = IFALIASZ - 1 }, + [IFLA_WEIGHT] = { .type = NETLINK_TYPE_U32 }, + [IFLA_OPERSTATE] = { .type = NETLINK_TYPE_U8 }, + [IFLA_LINKMODE] = { .type = NETLINK_TYPE_U8 }, + [IFLA_LINKINFO] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_info_type_system }, + [IFLA_NET_NS_PID] = { .type = NETLINK_TYPE_U32 }, + [IFLA_IFALIAS] = { .type = NETLINK_TYPE_STRING, .size = IFALIASZ - 1 }, /* [IFLA_NUM_VF], - [IFLA_VFINFO_LIST] = {. type = NLA_NESTED, }, + [IFLA_VFINFO_LIST] = {. type = NETLINK_TYPE_NESTED, }, [IFLA_STATS64], - [IFLA_VF_PORTS] = { .type = NLA_NESTED }, - [IFLA_PORT_SELF] = { .type = NLA_NESTED }, + [IFLA_VF_PORTS] = { .type = NETLINK_TYPE_NESTED }, + [IFLA_PORT_SELF] = { .type = NETLINK_TYPE_NESTED }, */ - [IFLA_AF_SPEC] = { .type = NLA_NESTED, .type_system = &rtnl_af_spec_type_system }, + [IFLA_AF_SPEC] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_af_spec_type_system }, /* [IFLA_VF_PORTS], [IFLA_PORT_SELF], [IFLA_AF_SPEC], */ - [IFLA_GROUP] = { .type = NLA_U32 }, - [IFLA_NET_NS_FD] = { .type = NLA_U32 }, - [IFLA_EXT_MASK] = { .type = NLA_U32 }, - [IFLA_PROMISCUITY] = { .type = NLA_U32 }, - [IFLA_NUM_TX_QUEUES] = { .type = NLA_U32 }, - [IFLA_NUM_RX_QUEUES] = { .type = NLA_U32 }, - [IFLA_CARRIER] = { .type = NLA_U8 }, + [IFLA_GROUP] = { .type = NETLINK_TYPE_U32 }, + [IFLA_NET_NS_FD] = { .type = NETLINK_TYPE_U32 }, + [IFLA_EXT_MASK] = { .type = NETLINK_TYPE_U32 }, + [IFLA_PROMISCUITY] = { .type = NETLINK_TYPE_U32 }, + [IFLA_NUM_TX_QUEUES] = { .type = NETLINK_TYPE_U32 }, + [IFLA_NUM_RX_QUEUES] = { .type = NETLINK_TYPE_U32 }, + [IFLA_CARRIER] = { .type = NETLINK_TYPE_U8 }, /* - [IFLA_PHYS_PORT_ID] = { .type = NLA_BINARY, .len = MAX_PHYS_PORT_ID_LEN }, + [IFLA_PHYS_PORT_ID] = { .type = NETLINK_TYPE_BINARY, .len = MAX_PHYS_PORT_ID_LEN }, */ }; static const NLTypeSystem rtnl_link_type_system = { - .max = ELEMENTSOF(rtnl_link_types) - 1, + .count = ELEMENTSOF(rtnl_link_types), .types = rtnl_link_types, }; /* IFA_FLAGS was defined in kernel 3.14, but we still support older * kernels where IFA_MAX is lower. */ static const NLType rtnl_address_types[CONST_MAX(IFA_MAX, IFA_FLAGS) + 1] = { - [IFA_ADDRESS] = { .type = NLA_IN_ADDR }, - [IFA_LOCAL] = { .type = NLA_IN_ADDR }, - [IFA_LABEL] = { .type = NLA_STRING, .size = IFNAMSIZ - 1 }, - [IFA_BROADCAST] = { .type = NLA_IN_ADDR }, /* 6? */ - [IFA_CACHEINFO] = { .type = NLA_CACHE_INFO, .size = sizeof(struct ifa_cacheinfo) }, + [IFA_ADDRESS] = { .type = NETLINK_TYPE_IN_ADDR }, + [IFA_LOCAL] = { .type = NETLINK_TYPE_IN_ADDR }, + [IFA_LABEL] = { .type = NETLINK_TYPE_STRING, .size = IFNAMSIZ - 1 }, + [IFA_BROADCAST] = { .type = NETLINK_TYPE_IN_ADDR }, /* 6? */ + [IFA_CACHEINFO] = { .type = NETLINK_TYPE_CACHE_INFO, .size = sizeof(struct ifa_cacheinfo) }, /* [IFA_ANYCAST], [IFA_MULTICAST], */ - [IFA_FLAGS] = { .type = NLA_U32 }, + [IFA_FLAGS] = { .type = NETLINK_TYPE_U32 }, }; static const NLTypeSystem rtnl_address_type_system = { - .max = ELEMENTSOF(rtnl_address_types) - 1, + .count = ELEMENTSOF(rtnl_address_types), .types = rtnl_address_types, }; static const NLType rtnl_route_types[RTA_MAX + 1] = { - [RTA_DST] = { .type = NLA_IN_ADDR }, /* 6? */ - [RTA_SRC] = { .type = NLA_IN_ADDR }, /* 6? */ - [RTA_IIF] = { .type = NLA_U32 }, - [RTA_OIF] = { .type = NLA_U32 }, - [RTA_GATEWAY] = { .type = NLA_IN_ADDR }, - [RTA_PRIORITY] = { .type = NLA_U32 }, - [RTA_PREFSRC] = { .type = NLA_IN_ADDR }, /* 6? */ + [RTA_DST] = { .type = NETLINK_TYPE_IN_ADDR }, /* 6? */ + [RTA_SRC] = { .type = NETLINK_TYPE_IN_ADDR }, /* 6? */ + [RTA_IIF] = { .type = NETLINK_TYPE_U32 }, + [RTA_OIF] = { .type = NETLINK_TYPE_U32 }, + [RTA_GATEWAY] = { .type = NETLINK_TYPE_IN_ADDR }, + [RTA_PRIORITY] = { .type = NETLINK_TYPE_U32 }, + [RTA_PREFSRC] = { .type = NETLINK_TYPE_IN_ADDR }, /* 6? */ /* - [RTA_METRICS] = { .type = NLA_NESTED }, + [RTA_METRICS] = { .type = NETLINK_TYPE_NESTED }, [RTA_MULTIPATH] = { .len = sizeof(struct rtnexthop) }, */ - [RTA_FLOW] = { .type = NLA_U32 }, /* 6? */ + [RTA_FLOW] = { .type = NETLINK_TYPE_U32 }, /* 6? */ /* RTA_CACHEINFO, RTA_TABLE, @@ -417,65 +473,95 @@ static const NLType rtnl_route_types[RTA_MAX + 1] = { }; static const NLTypeSystem rtnl_route_type_system = { - .max = ELEMENTSOF(rtnl_route_types) - 1, + .count = ELEMENTSOF(rtnl_route_types), .types = rtnl_route_types, }; static const NLType rtnl_neigh_types[NDA_MAX + 1] = { - [NDA_DST] = { .type = NLA_IN_ADDR }, - [NDA_LLADDR] = { .type = NLA_ETHER_ADDR }, - [NDA_CACHEINFO] = { .type = NLA_CACHE_INFO, .size = sizeof(struct nda_cacheinfo) }, - [NDA_PROBES] = { .type = NLA_U32 }, - [NDA_VLAN] = { .type = NLA_U16 }, - [NDA_PORT] = { .type = NLA_U16 }, - [NDA_VNI] = { .type = NLA_U32 }, - [NDA_IFINDEX] = { .type = NLA_U32 }, + [NDA_DST] = { .type = NETLINK_TYPE_IN_ADDR }, + [NDA_LLADDR] = { .type = NETLINK_TYPE_ETHER_ADDR }, + [NDA_CACHEINFO] = { .type = NETLINK_TYPE_CACHE_INFO, .size = sizeof(struct nda_cacheinfo) }, + [NDA_PROBES] = { .type = NETLINK_TYPE_U32 }, + [NDA_VLAN] = { .type = NETLINK_TYPE_U16 }, + [NDA_PORT] = { .type = NETLINK_TYPE_U16 }, + [NDA_VNI] = { .type = NETLINK_TYPE_U32 }, + [NDA_IFINDEX] = { .type = NETLINK_TYPE_U32 }, }; static const NLTypeSystem rtnl_neigh_type_system = { - .max = ELEMENTSOF(rtnl_neigh_types) - 1, + .count = ELEMENTSOF(rtnl_neigh_types), .types = rtnl_neigh_types, }; static const NLType rtnl_types[RTM_MAX + 1] = { - [NLMSG_DONE] = { .type = NLA_META, .size = 0 }, - [NLMSG_ERROR] = { .type = NLA_META, .size = sizeof(struct nlmsgerr) }, - [RTM_NEWLINK] = { .type = NLA_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) }, - [RTM_DELLINK] = { .type = NLA_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) }, - [RTM_GETLINK] = { .type = NLA_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) }, - [RTM_SETLINK] = { .type = NLA_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) }, - [RTM_NEWADDR] = { .type = NLA_NESTED, .type_system = &rtnl_address_type_system, .size = sizeof(struct ifaddrmsg) }, - [RTM_DELADDR] = { .type = NLA_NESTED, .type_system = &rtnl_address_type_system, .size = sizeof(struct ifaddrmsg) }, - [RTM_GETADDR] = { .type = NLA_NESTED, .type_system = &rtnl_address_type_system, .size = sizeof(struct ifaddrmsg) }, - [RTM_NEWROUTE] = { .type = NLA_NESTED, .type_system = &rtnl_route_type_system, .size = sizeof(struct rtmsg) }, - [RTM_DELROUTE] = { .type = NLA_NESTED, .type_system = &rtnl_route_type_system, .size = sizeof(struct rtmsg) }, - [RTM_GETROUTE] = { .type = NLA_NESTED, .type_system = &rtnl_route_type_system, .size = sizeof(struct rtmsg) }, - [RTM_NEWNEIGH] = { .type = NLA_NESTED, .type_system = &rtnl_neigh_type_system, .size = sizeof(struct ndmsg) }, - [RTM_DELNEIGH] = { .type = NLA_NESTED, .type_system = &rtnl_neigh_type_system, .size = sizeof(struct ndmsg) }, - [RTM_GETNEIGH] = { .type = NLA_NESTED, .type_system = &rtnl_neigh_type_system, .size = sizeof(struct ndmsg) }, -}; - -const NLTypeSystem rtnl_type_system = { - .max = ELEMENTSOF(rtnl_types) - 1, + [NLMSG_DONE] = { .type = NETLINK_TYPE_NESTED, .type_system = &empty_type_system, .size = 0 }, + [NLMSG_ERROR] = { .type = NETLINK_TYPE_NESTED, .type_system = &empty_type_system, .size = sizeof(struct nlmsgerr) }, + [RTM_NEWLINK] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) }, + [RTM_DELLINK] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) }, + [RTM_GETLINK] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) }, + [RTM_SETLINK] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) }, + [RTM_NEWADDR] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_address_type_system, .size = sizeof(struct ifaddrmsg) }, + [RTM_DELADDR] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_address_type_system, .size = sizeof(struct ifaddrmsg) }, + [RTM_GETADDR] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_address_type_system, .size = sizeof(struct ifaddrmsg) }, + [RTM_NEWROUTE] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_route_type_system, .size = sizeof(struct rtmsg) }, + [RTM_DELROUTE] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_route_type_system, .size = sizeof(struct rtmsg) }, + [RTM_GETROUTE] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_route_type_system, .size = sizeof(struct rtmsg) }, + [RTM_NEWNEIGH] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_neigh_type_system, .size = sizeof(struct ndmsg) }, + [RTM_DELNEIGH] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_neigh_type_system, .size = sizeof(struct ndmsg) }, + [RTM_GETNEIGH] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_neigh_type_system, .size = sizeof(struct ndmsg) }, +}; + +const NLTypeSystem type_system_root = { + .count = ELEMENTSOF(rtnl_types), .types = rtnl_types, }; -int type_system_get_type(const NLTypeSystem *type_system, const NLType **ret, uint16_t type) { - const NLType *nl_type; +uint16_t type_get_type(const NLType *type) { + assert(type); + return type->type; +} +size_t type_get_size(const NLType *type) { + assert(type); + return type->size; +} + +void type_get_type_system(const NLType *nl_type, const NLTypeSystem **ret) { + assert(nl_type); assert(ret); + assert(nl_type->type == NETLINK_TYPE_NESTED); + assert(nl_type->type_system); - if (!type_system) - type_system = &rtnl_type_system; + *ret = nl_type->type_system; +} +void type_get_type_system_union(const NLType *nl_type, const NLTypeSystemUnion **ret) { + assert(nl_type); + assert(ret); + assert(nl_type->type == NETLINK_TYPE_UNION); + assert(nl_type->type_system_union); + + *ret = nl_type->type_system_union; +} + +uint16_t type_system_get_count(const NLTypeSystem *type_system) { + assert(type_system); + return type_system->count; +} + +int type_system_get_type(const NLTypeSystem *type_system, const NLType **ret, uint16_t type) { + const NLType *nl_type; + + assert(ret); + assert(type_system); assert(type_system->types); - if (type > type_system->max) + if (type >= type_system->count) return -EOPNOTSUPP; nl_type = &type_system->types[type]; - if (nl_type->type == NLA_UNSPEC) + if (nl_type->type == NETLINK_TYPE_UNSPEC) return -EOPNOTSUPP; *ret = nl_type; @@ -493,11 +579,7 @@ int type_system_get_type_system(const NLTypeSystem *type_system, const NLTypeSys if (r < 0) return r; - assert(nl_type->type == NLA_NESTED); - assert(nl_type->type_system); - - *ret = nl_type->type_system; - + type_get_type_system(nl_type, ret); return 0; } @@ -511,11 +593,7 @@ int type_system_get_type_system_union(const NLTypeSystem *type_system, const NLT if (r < 0) return r; - assert(nl_type->type == NLA_UNION); - assert(nl_type->type_system_union); - - *ret = nl_type->type_system_union; - + type_get_type_system_union(nl_type, ret); return 0; } @@ -552,7 +630,7 @@ int type_system_union_protocol_get_type_system(const NLTypeSystemUnion *type_sys return -EOPNOTSUPP; type_system = &type_system_union->type_systems[protocol]; - if (type_system->max == 0) + if (!type_system->types) return -EOPNOTSUPP; *ret = type_system; diff --git a/src/libsystemd/sd-netlink/netlink-types.h b/src/libsystemd/sd-netlink/netlink-types.h index de1544bf36..a210163241 100644 --- a/src/libsystemd/sd-netlink/netlink-types.h +++ b/src/libsystemd/sd-netlink/netlink-types.h @@ -22,18 +22,17 @@ ***/ enum { - NLA_UNSPEC, - NLA_META, - NLA_U8, - NLA_U16, - NLA_U32, - NLA_U64, - NLA_STRING, - NLA_IN_ADDR, - NLA_ETHER_ADDR, - NLA_CACHE_INFO, - NLA_NESTED, - NLA_UNION, + NETLINK_TYPE_UNSPEC, + NETLINK_TYPE_U8, /* NLA_U8 */ + NETLINK_TYPE_U16, /* NLA_U16 */ + NETLINK_TYPE_U32, /* NLA_U32 */ + NETLINK_TYPE_U64, /* NLA_U64 */ + NETLINK_TYPE_STRING, /* NLA_STRING */ + NETLINK_TYPE_IN_ADDR, + NETLINK_TYPE_ETHER_ADDR, + NETLINK_TYPE_CACHE_INFO, + NETLINK_TYPE_NESTED, /* NLA_NESTED */ + NETLINK_TYPE_UNION, }; typedef enum NLMatchType { @@ -53,18 +52,14 @@ struct NLTypeSystemUnion { const NLTypeSystem *type_systems; }; -struct NLTypeSystem { - uint16_t max; - const NLType *types; -}; +extern const NLTypeSystem type_system_root; -struct NLType { - uint16_t type; - size_t size; - const NLTypeSystem *type_system; - const NLTypeSystemUnion *type_system_union; -}; +uint16_t type_get_type(const NLType *type); +size_t type_get_size(const NLType *type); +void type_get_type_system(const NLType *type, const NLTypeSystem **ret); +void type_get_type_system_union(const NLType *type, const NLTypeSystemUnion **ret); +uint16_t type_system_get_count(const NLTypeSystem *type_system); int type_system_get_type(const NLTypeSystem *type_system, const NLType **ret, uint16_t type); int type_system_get_type_system(const NLTypeSystem *type_system, const NLTypeSystem **ret, uint16_t type); int type_system_get_type_system_union(const NLTypeSystem *type_system, const NLTypeSystemUnion **ret, uint16_t type); @@ -95,25 +90,3 @@ typedef enum NLUnionLinkInfoData { const char *nl_union_link_info_data_to_string(NLUnionLinkInfoData p) _const_; NLUnionLinkInfoData nl_union_link_info_data_from_string(const char *p) _pure_; - -/* Maximum ARP IP target defined in kernel */ -#define BOND_MAX_ARP_TARGETS 16 - -typedef enum BondArpTargets { - BOND_ARP_TARGETS_0, - BOND_ARP_TARGETS_1, - BOND_ARP_TARGETS_2, - BOND_ARP_TARGETS_3, - BOND_ARP_TARGETS_4, - BOND_ARP_TARGETS_5, - BOND_ARP_TARGETS_6, - BOND_ARP_TARGETS_7, - BOND_ARP_TARGETS_8, - BOND_ARP_TARGETS_9, - BOND_ARP_TARGETS_10, - BOND_ARP_TARGETS_11, - BOND_ARP_TARGETS_12, - BOND_ARP_TARGETS_13, - BOND_ARP_TARGETS_14, - BOND_ARP_TARGETS_MAX = BOND_MAX_ARP_TARGETS, -} BondArpTargets; |