1
0
mirror of https://github.com/systemd/systemd synced 2026-03-20 03:54:45 +01:00

Compare commits

..

No commits in common. "d3a047b9d1277c92657ad69e210a60e0dbb2f430" and "e8f4bf33d8a6123ad8ae3955c989e36972f4884d" have entirely different histories.

5 changed files with 121 additions and 106 deletions

View File

@ -1720,7 +1720,7 @@ IPv6Token=prefixstable:2002:da8:1::</programlisting></para>
<para>This option should only be set to true when <varname>MACAddressPolicy=</varname> is <para>This option should only be set to true when <varname>MACAddressPolicy=</varname> is
set to <option>random</option> (see set to <option>random</option> (see
<citerefentry><refentrytitle>systemd.link</refentrytitle><manvolnum>5</manvolnum></citerefentry>). <citerefentry project='man-pages'><refentrytitle>systemd.link</refentrytitle><manvolnum>5</manvolnum></citerefentry>).
</para> </para>
<para>When true, <varname>SendHostname=</varname>, <varname>ClientIdentifier=</varname>, <para>When true, <varname>SendHostname=</varname>, <varname>ClientIdentifier=</varname>,

View File

@ -34,9 +34,7 @@ static int genl_message_new(sd_netlink *nl, sd_genl_family_t family, uint16_t nl
size_t size; size_t size;
int r; int r;
assert(nl); assert_return(nl->protocol == NETLINK_GENERIC, -EINVAL);
assert(nl->protocol == NETLINK_GENERIC);
assert(ret);
r = type_system_get_type(&genl_family_type_system_root, &genl_cmd_type, family); r = type_system_get_type(&genl_family_type_system_root, &genl_cmd_type, family);
if (r < 0) if (r < 0)
@ -74,28 +72,24 @@ static int genl_message_new(sd_netlink *nl, sd_genl_family_t family, uint16_t nl
return 0; return 0;
} }
static int lookup_nlmsg_type(sd_netlink *nl, sd_genl_family_t family, uint16_t *ret) { static int lookup_id(sd_netlink *nl, sd_genl_family_t family, uint16_t *id) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL; _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
uint16_t u; uint16_t u;
void *v; void *v;
int r; int r;
assert(nl);
assert(nl->protocol == NETLINK_GENERIC);
assert(ret);
if (family == SD_GENL_ID_CTRL) { if (family == SD_GENL_ID_CTRL) {
*ret = GENL_ID_CTRL; *id = GENL_ID_CTRL;
return 0; return 0;
} }
v = hashmap_get(nl->genl_family_to_nlmsg_type, INT_TO_PTR(family)); v = hashmap_get(nl->genl_family_to_nlmsg_type, INT_TO_PTR(family));
if (v) { if (v) {
*ret = PTR_TO_UINT(v); *id = PTR_TO_UINT(v);
return 0; return 0;
} }
r = genl_message_new(nl, SD_GENL_ID_CTRL, GENL_ID_CTRL, CTRL_CMD_GETFAMILY, &req); r = sd_genl_message_new(nl, SD_GENL_ID_CTRL, CTRL_CMD_GETFAMILY, &req);
if (r < 0) if (r < 0)
return r; return r;
@ -119,40 +113,36 @@ static int lookup_nlmsg_type(sd_netlink *nl, sd_genl_family_t family, uint16_t *
if (r < 0) if (r < 0)
return r; return r;
*ret = u; *id = u;
return 0; return 0;
} }
int sd_genl_message_new(sd_netlink *nl, sd_genl_family_t family, uint8_t cmd, sd_netlink_message **ret) { int sd_genl_message_new(sd_netlink *nl, sd_genl_family_t family, uint8_t cmd, sd_netlink_message **ret) {
uint16_t nlmsg_type = 0; /* Unnecessary initialization to appease gcc */ uint16_t id = 0; /* Unnecessary initialization to appease gcc */
int r; int r;
assert_return(nl, -EINVAL); r = lookup_id(nl, family, &id);
assert_return(nl->protocol == NETLINK_GENERIC, -EINVAL);
assert_return(ret, -EINVAL);
r = lookup_nlmsg_type(nl, family, &nlmsg_type);
if (r < 0) if (r < 0)
return r; return r;
return genl_message_new(nl, family, nlmsg_type, cmd, ret); return genl_message_new(nl, family, id, cmd, ret);
} }
int nlmsg_type_to_genl_family(const sd_netlink *nl, uint16_t nlmsg_type, sd_genl_family_t *ret) { int nlmsg_type_to_genl_family(const sd_netlink *nl, uint16_t type, sd_genl_family_t *ret) {
void *p; void *p;
assert(nl); assert_return(nl, -EINVAL);
assert(nl->protocol == NETLINK_GENERIC); assert_return(nl->protocol == NETLINK_GENERIC, -EINVAL);
assert(ret); assert(ret);
if (nlmsg_type == NLMSG_ERROR) if (type == NLMSG_ERROR)
*ret = SD_GENL_ERROR; *ret = SD_GENL_ERROR;
else if (nlmsg_type == NLMSG_DONE) else if (type == NLMSG_DONE)
*ret = SD_GENL_DONE; *ret = SD_GENL_DONE;
else if (nlmsg_type == GENL_ID_CTRL) else if (type == GENL_ID_CTRL)
*ret = SD_GENL_ID_CTRL; *ret = SD_GENL_ID_CTRL;
else { else {
p = hashmap_get(nl->nlmsg_type_to_genl_family, UINT_TO_PTR(nlmsg_type)); p = hashmap_get(nl->nlmsg_type_to_genl_family, UINT_TO_PTR(type));
if (!p) if (!p)
return -EOPNOTSUPP; return -EOPNOTSUPP;
@ -162,18 +152,18 @@ int nlmsg_type_to_genl_family(const sd_netlink *nl, uint16_t nlmsg_type, sd_genl
return 0; return 0;
} }
int sd_genl_message_get_family(sd_netlink *nl, sd_netlink_message *m, sd_genl_family_t *ret) { int sd_genl_message_get_family(sd_netlink *nl, sd_netlink_message *m, sd_genl_family_t *family) {
uint16_t nlmsg_type; uint16_t type;
int r; int r;
assert_return(m, -EINVAL);
assert_return(nl, -EINVAL); assert_return(nl, -EINVAL);
assert_return(nl->protocol == NETLINK_GENERIC, -EINVAL); assert_return(nl->protocol == NETLINK_GENERIC, -EINVAL);
assert_return(m, -EINVAL); assert_return(family, -EINVAL);
assert_return(ret, -EINVAL);
r = sd_netlink_message_get_type(m, &nlmsg_type); r = sd_netlink_message_get_type(m, &type);
if (r < 0) if (r < 0)
return r; return r;
return nlmsg_type_to_genl_family(nl, nlmsg_type, ret); return nlmsg_type_to_genl_family(nl, type, family);
} }

View File

@ -35,7 +35,8 @@ static int broadcast_groups_get(sd_netlink *nl) {
assert(nl); assert(nl);
assert(nl->fd >= 0); assert(nl->fd >= 0);
if (getsockopt(nl->fd, SOL_NETLINK, NETLINK_LIST_MEMBERSHIPS, NULL, &len) < 0) { r = getsockopt(nl->fd, SOL_NETLINK, NETLINK_LIST_MEMBERSHIPS, NULL, &len);
if (r < 0) {
if (errno != ENOPROTOOPT) if (errno != ENOPROTOOPT)
return -errno; return -errno;
@ -52,18 +53,23 @@ static int broadcast_groups_get(sd_netlink *nl) {
old_len = len; old_len = len;
if (getsockopt(nl->fd, SOL_NETLINK, NETLINK_LIST_MEMBERSHIPS, groups, &len) < 0) r = getsockopt(nl->fd, SOL_NETLINK, NETLINK_LIST_MEMBERSHIPS, groups, &len);
if (r < 0)
return -errno; return -errno;
if (old_len != len) if (old_len != len)
return -EIO; return -EIO;
r = hashmap_ensure_allocated(&nl->broadcast_group_refs, NULL);
if (r < 0)
return r;
for (unsigned i = 0; i < len; i++) for (unsigned i = 0; i < len; i++)
for (unsigned j = 0; j < sizeof(uint32_t) * 8; j++) for (unsigned j = 0; j < sizeof(uint32_t) * 8; j++)
if (groups[i] & (1U << j)) { if (groups[i] & (1U << j)) {
unsigned group = i * sizeof(uint32_t) * 8 + j + 1; unsigned group = i * sizeof(uint32_t) * 8 + j + 1;
r = hashmap_ensure_put(&nl->broadcast_group_refs, NULL, UINT_TO_PTR(group), UINT_TO_PTR(1)); r = hashmap_put(nl->broadcast_group_refs, UINT_TO_PTR(group), UINT_TO_PTR(1));
if (r < 0) if (r < 0)
return r; return r;
} }
@ -82,7 +88,7 @@ int socket_bind(sd_netlink *nl) {
addrlen = sizeof(nl->sockaddr); addrlen = sizeof(nl->sockaddr);
r = bind(nl->fd, &nl->sockaddr.sa, addrlen); r = bind(nl->fd, &nl->sockaddr.sa, addrlen);
/* ignore EINVAL to allow binding an already bound socket */ /* ignore EINVAL to allow opening an already bound socket */
if (r < 0 && errno != EINVAL) if (r < 0 && errno != EINVAL)
return -errno; return -errno;
@ -104,11 +110,11 @@ static int broadcast_group_set_ref(sd_netlink *nl, unsigned group, unsigned n_re
assert(nl); assert(nl);
r = hashmap_ensure_allocated(&nl->broadcast_group_refs, NULL); r = hashmap_replace(nl->broadcast_group_refs, UINT_TO_PTR(group), UINT_TO_PTR(n_ref));
if (r < 0) if (r < 0)
return r; return r;
return hashmap_replace(nl->broadcast_group_refs, UINT_TO_PTR(group), UINT_TO_PTR(n_ref)); return 0;
} }
static int broadcast_group_join(sd_netlink *nl, unsigned group) { static int broadcast_group_join(sd_netlink *nl, unsigned group) {
@ -130,15 +136,23 @@ int socket_broadcast_group_ref(sd_netlink *nl, unsigned group) {
n_ref++; n_ref++;
r = hashmap_ensure_allocated(&nl->broadcast_group_refs, NULL);
if (r < 0)
return r;
r = broadcast_group_set_ref(nl, group, n_ref); r = broadcast_group_set_ref(nl, group, n_ref);
if (r < 0) if (r < 0)
return r; return r;
if (n_ref > 1) if (n_ref > 1)
/* already in the group */ /* not yet in the group */
return 0; return 0;
return broadcast_group_join(nl, group); r = broadcast_group_join(nl, group);
if (r < 0)
return r;
return 0;
} }
static int broadcast_group_leave(sd_netlink *nl, unsigned group) { static int broadcast_group_leave(sd_netlink *nl, unsigned group) {
@ -160,8 +174,8 @@ int socket_broadcast_group_unref(sd_netlink *nl, unsigned group) {
assert(nl); assert(nl);
n_ref = broadcast_group_get_ref(nl, group); n_ref = broadcast_group_get_ref(nl, group);
if (n_ref == 0)
return 0; assert(n_ref > 0);
n_ref--; n_ref--;
@ -173,12 +187,19 @@ int socket_broadcast_group_unref(sd_netlink *nl, unsigned group) {
/* still refs left */ /* still refs left */
return 0; return 0;
return broadcast_group_leave(nl, group); r = broadcast_group_leave(nl, group);
if (r < 0)
return r;
return 0;
} }
/* returns the number of bytes sent, or a negative error code */ /* returns the number of bytes sent, or a negative error code */
int socket_write_message(sd_netlink *nl, sd_netlink_message *m) { int socket_write_message(sd_netlink *nl, sd_netlink_message *m) {
union sockaddr_union addr = { union {
struct sockaddr sa;
struct sockaddr_nl nl;
} addr = {
.nl.nl_family = AF_NETLINK, .nl.nl_family = AF_NETLINK,
}; };
ssize_t k; ssize_t k;
@ -187,7 +208,8 @@ int socket_write_message(sd_netlink *nl, sd_netlink_message *m) {
assert(m); assert(m);
assert(m->hdr); assert(m->hdr);
k = sendto(nl->fd, m->hdr, m->hdr->nlmsg_len, 0, &addr.sa, sizeof(addr)); k = sendto(nl->fd, m->hdr, m->hdr->nlmsg_len,
0, &addr.sa, sizeof(addr));
if (k < 0) if (k < 0)
return -errno; return -errno;
@ -196,24 +218,22 @@ int socket_write_message(sd_netlink *nl, sd_netlink_message *m) {
int socket_writev_message(sd_netlink *nl, sd_netlink_message **m, size_t msgcount) { int socket_writev_message(sd_netlink *nl, sd_netlink_message **m, size_t msgcount) {
_cleanup_free_ struct iovec *iovs = NULL; _cleanup_free_ struct iovec *iovs = NULL;
ssize_t k;
assert(nl); assert(nl);
assert(m); assert(m);
assert(msgcount > 0); assert(msgcount > 0);
iovs = new(struct iovec, msgcount); iovs = new0(struct iovec, msgcount);
if (!iovs) if (!iovs)
return -ENOMEM; return -ENOMEM;
for (size_t i = 0; i < msgcount; i++) { for (size_t i = 0; i < msgcount; i++) {
assert(m[i]->hdr); assert(m[i]->hdr != NULL);
assert(m[i]->hdr->nlmsg_len > 0); assert(m[i]->hdr->nlmsg_len > 0);
iovs[i] = IOVEC_MAKE(m[i]->hdr, m[i]->hdr->nlmsg_len); iovs[i] = IOVEC_MAKE(m[i]->hdr, m[i]->hdr->nlmsg_len);
} }
k = writev(nl->fd, iovs, msgcount); ssize_t k = writev(nl->fd, iovs, msgcount);
if (k < 0) if (k < 0)
return -errno; return -errno;
@ -246,7 +266,7 @@ static int socket_recv_message(int fd, struct iovec *iov, uint32_t *ret_mcast_gr
if (sender.nl.nl_pid != 0) { if (sender.nl.nl_pid != 0) {
/* not from the kernel, ignore */ /* not from the kernel, ignore */
log_debug("rtnl: ignoring message from PID %"PRIu32, sender.nl.nl_pid); log_debug("rtnl: ignoring message from portid %"PRIu32, sender.nl.nl_pid);
if (peek) { if (peek) {
/* drop the message */ /* drop the message */
@ -316,13 +336,14 @@ int socket_read_message(sd_netlink *rtnl) {
if (NLMSG_OK(rtnl->rbuffer, len) && rtnl->rbuffer->nlmsg_flags & NLM_F_MULTI) { if (NLMSG_OK(rtnl->rbuffer, len) && rtnl->rbuffer->nlmsg_flags & NLM_F_MULTI) {
multi_part = true; multi_part = true;
for (i = 0; i < rtnl->rqueue_partial_size; i++) for (i = 0; i < rtnl->rqueue_partial_size; i++) {
if (rtnl_message_get_serial(rtnl->rqueue_partial[i]) == if (rtnl_message_get_serial(rtnl->rqueue_partial[i]) ==
rtnl->rbuffer->nlmsg_seq) { rtnl->rbuffer->nlmsg_seq) {
first = rtnl->rqueue_partial[i]; first = rtnl->rqueue_partial[i];
break; break;
} }
} }
}
for (struct nlmsghdr *new_msg = rtnl->rbuffer; NLMSG_OK(new_msg, len) && !done; new_msg = NLMSG_NEXT(new_msg, len)) { for (struct nlmsghdr *new_msg = rtnl->rbuffer; NLMSG_OK(new_msg, len) && !done; new_msg = NLMSG_NEXT(new_msg, len)) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;

View File

@ -254,13 +254,12 @@ int sd_netlink_send(sd_netlink *nl,
return 1; return 1;
} }
int sd_netlink_sendv( int sd_netlink_sendv(sd_netlink *nl,
sd_netlink *nl,
sd_netlink_message **messages, sd_netlink_message **messages,
size_t msgcount, size_t msgcount,
uint32_t **ret_serial) { uint32_t **ret_serial) {
_cleanup_free_ uint32_t *serials = NULL; _cleanup_free_ uint32_t *serials = NULL;
unsigned i;
int r; int r;
assert_return(nl, -EINVAL); assert_return(nl, -EINVAL);
@ -269,14 +268,13 @@ int sd_netlink_sendv(
assert_return(msgcount > 0, -EINVAL); assert_return(msgcount > 0, -EINVAL);
if (ret_serial) { if (ret_serial) {
serials = new(uint32_t, msgcount); serials = new0(uint32_t, msgcount);
if (!serials) if (!serials)
return -ENOMEM; return -ENOMEM;
} }
for (unsigned i = 0; i < msgcount; i++) { for (i = 0; i < msgcount; i++) {
assert_return(!messages[i]->sealed, -EPERM); assert_return(!messages[i]->sealed, -EPERM);
rtnl_seal_message(nl, messages[i]); rtnl_seal_message(nl, messages[i]);
if (serials) if (serials)
serials[i] = rtnl_message_get_serial(messages[i]); serials[i] = rtnl_message_get_serial(messages[i]);
@ -525,7 +523,7 @@ static usec_t calc_elapse(uint64_t usec) {
return usec_add(now(CLOCK_MONOTONIC), usec); return usec_add(now(CLOCK_MONOTONIC), usec);
} }
static int rtnl_poll(sd_netlink *rtnl, bool need_more, usec_t timeout_usec) { static int rtnl_poll(sd_netlink *rtnl, bool need_more, uint64_t timeout_usec) {
usec_t m = USEC_INFINITY; usec_t m = USEC_INFINITY;
int r, e; int r, e;
@ -541,18 +539,23 @@ static int rtnl_poll(sd_netlink *rtnl, bool need_more, usec_t timeout_usec) {
e |= POLLIN; e |= POLLIN;
else { else {
usec_t until; usec_t until;
/* Caller wants to process if there is something to /* Caller wants to process if there is something to
* process, but doesn't care otherwise */ * process, but doesn't care otherwise */
r = sd_netlink_get_timeout(rtnl, &until); r = sd_netlink_get_timeout(rtnl, &until);
if (r < 0) if (r < 0)
return r; return r;
if (r > 0) {
m = usec_sub_unsigned(until, now(CLOCK_MONOTONIC)); usec_t nw;
nw = now(CLOCK_MONOTONIC);
m = until > nw ? until - nw : 0;
}
} }
r = fd_wait_for_event(rtnl->fd, e, MIN(m, timeout_usec)); if (timeout_usec != UINT64_MAX && (m == USEC_INFINITY || timeout_usec < m))
m = timeout_usec;
r = fd_wait_for_event(rtnl->fd, e, m);
if (r <= 0) if (r <= 0)
return r; return r;
@ -590,7 +593,6 @@ int sd_netlink_call_async(
void *userdata, void *userdata,
uint64_t usec, uint64_t usec,
const char *description) { const char *description) {
_cleanup_free_ sd_netlink_slot *slot = NULL; _cleanup_free_ sd_netlink_slot *slot = NULL;
int r, k; int r, k;
@ -646,12 +648,10 @@ int sd_netlink_call_async(
return k; return k;
} }
int sd_netlink_read( int sd_netlink_read(sd_netlink *rtnl,
sd_netlink *rtnl,
uint32_t serial, uint32_t serial,
uint64_t usec, uint64_t usec,
sd_netlink_message **ret) { sd_netlink_message **ret) {
usec_t timeout; usec_t timeout;
int r; int r;
@ -662,15 +662,16 @@ int sd_netlink_read(
for (;;) { for (;;) {
usec_t left; usec_t left;
unsigned i;
for (unsigned i = 0; i < rtnl->rqueue_size; i++) { for (i = 0; i < rtnl->rqueue_size; i++) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *incoming = NULL;
uint32_t received_serial; uint32_t received_serial;
uint16_t type;
received_serial = rtnl_message_get_serial(rtnl->rqueue[i]); received_serial = rtnl_message_get_serial(rtnl->rqueue[i]);
if (received_serial != serial)
continue; if (received_serial == serial) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *incoming = NULL;
uint16_t type;
incoming = rtnl->rqueue[i]; incoming = rtnl->rqueue[i];
@ -694,8 +695,10 @@ int sd_netlink_read(
if (ret) if (ret)
*ret = TAKE_PTR(incoming); *ret = TAKE_PTR(incoming);
return 1; return 1;
} }
}
r = socket_read_message(rtnl); r = socket_read_message(rtnl);
if (r < 0) if (r < 0)
@ -711,24 +714,22 @@ int sd_netlink_read(
if (n >= timeout) if (n >= timeout)
return -ETIMEDOUT; return -ETIMEDOUT;
left = usec_sub_unsigned(timeout, n); left = timeout - n;
} else } else
left = USEC_INFINITY; left = UINT64_MAX;
r = rtnl_poll(rtnl, true, left); r = rtnl_poll(rtnl, true, left);
if (r < 0) if (r < 0)
return r; return r;
if (r == 0) else if (r == 0)
return -ETIMEDOUT; return -ETIMEDOUT;
} }
} }
int sd_netlink_call( int sd_netlink_call(sd_netlink *rtnl,
sd_netlink *rtnl,
sd_netlink_message *message, sd_netlink_message *message,
uint64_t usec, uint64_t usec,
sd_netlink_message **ret) { sd_netlink_message **ret) {
uint32_t serial; uint32_t serial;
int r; int r;
@ -747,7 +748,10 @@ int sd_netlink_get_events(sd_netlink *rtnl) {
assert_return(rtnl, -EINVAL); assert_return(rtnl, -EINVAL);
assert_return(!rtnl_pid_changed(rtnl), -ECHILD); assert_return(!rtnl_pid_changed(rtnl), -ECHILD);
return rtnl->rqueue_size == 0 ? POLLIN : 0; if (rtnl->rqueue_size == 0)
return POLLIN;
else
return 0;
} }
int sd_netlink_get_timeout(sd_netlink *rtnl, uint64_t *timeout_usec) { int sd_netlink_get_timeout(sd_netlink *rtnl, uint64_t *timeout_usec) {

View File

@ -251,8 +251,8 @@ int sd_nfnl_nft_message_add_setelem_end(sd_netlink_message *m);
/* genl */ /* genl */
int sd_genl_socket_open(sd_netlink **nl); int sd_genl_socket_open(sd_netlink **nl);
int sd_genl_message_new(sd_netlink *nl, sd_genl_family_t family, uint8_t cmd, sd_netlink_message **ret); int sd_genl_message_new(sd_netlink *nl, sd_genl_family_t family, uint8_t cmd, sd_netlink_message **m);
int sd_genl_message_get_family(sd_netlink *nl, sd_netlink_message *m, sd_genl_family_t *ret); int sd_genl_message_get_family(sd_netlink *nl, sd_netlink_message *m, sd_genl_family_t *family);
/* slot */ /* slot */
sd_netlink_slot *sd_netlink_slot_ref(sd_netlink_slot *nl); sd_netlink_slot *sd_netlink_slot_ref(sd_netlink_slot *nl);