mirror of
https://github.com/systemd/systemd.git
synced 2025-02-03 17:47:28 +03:00
nss-myhostname: use _cleanup_ and split function into two
The triply nested loop is just too much. Let's split out the middle loop's body, so the whole thing is easier to read. Also modernize the style a bit, using structure initialization to avoid memset and such.
This commit is contained in:
parent
7a22620612
commit
d73c3269cd
@ -35,49 +35,15 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "ifconf.h"
|
#include "ifconf.h"
|
||||||
|
#include "macro.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
int ifconf_acquire_addresses(struct address **_list, unsigned *_n_list) {
|
#define SEQ 4711
|
||||||
|
|
||||||
struct {
|
static int read_reply(int fd, struct address **list, unsigned *n_list) {
|
||||||
struct nlmsghdr hdr;
|
|
||||||
struct rtgenmsg gen;
|
|
||||||
} req;
|
|
||||||
struct rtgenmsg *gen;
|
|
||||||
int fd, r, on = 1;
|
|
||||||
uint32_t seq = 4711;
|
|
||||||
struct address *list = NULL;
|
|
||||||
unsigned n_list = 0;
|
|
||||||
|
|
||||||
fd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
|
|
||||||
if (fd < 0)
|
|
||||||
return -errno;
|
|
||||||
|
|
||||||
if (setsockopt(fd, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)) < 0) {
|
|
||||||
r = -errno;
|
|
||||||
goto finish;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(&req, 0, sizeof(req));
|
|
||||||
req.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg));
|
|
||||||
req.hdr.nlmsg_type = RTM_GETADDR;
|
|
||||||
req.hdr.nlmsg_flags = NLM_F_REQUEST|NLM_F_DUMP|NLM_F_ACK;
|
|
||||||
req.hdr.nlmsg_seq = seq;
|
|
||||||
req.hdr.nlmsg_pid = 0;
|
|
||||||
|
|
||||||
gen = NLMSG_DATA(&req.hdr);
|
|
||||||
gen->rtgen_family = AF_UNSPEC;
|
|
||||||
|
|
||||||
if (send(fd, &req, req.hdr.nlmsg_len, 0) < 0) {
|
|
||||||
r = -errno;
|
|
||||||
goto finish;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
ssize_t bytes;
|
ssize_t bytes;
|
||||||
struct msghdr msg;
|
|
||||||
struct cmsghdr *cmsg;
|
struct cmsghdr *cmsg;
|
||||||
struct ucred *ucred;
|
struct ucred *ucred;
|
||||||
struct iovec iov;
|
|
||||||
struct nlmsghdr *p;
|
struct nlmsghdr *p;
|
||||||
uint8_t cred_buffer[CMSG_SPACE(sizeof(struct ucred))];
|
uint8_t cred_buffer[CMSG_SPACE(sizeof(struct ucred))];
|
||||||
struct {
|
struct {
|
||||||
@ -85,35 +51,34 @@ int ifconf_acquire_addresses(struct address **_list, unsigned *_n_list) {
|
|||||||
struct ifaddrmsg ifaddrmsg;
|
struct ifaddrmsg ifaddrmsg;
|
||||||
uint8_t payload[16*1024];
|
uint8_t payload[16*1024];
|
||||||
} resp;
|
} resp;
|
||||||
|
struct iovec iov = {
|
||||||
|
.iov_base = &resp,
|
||||||
|
.iov_len = sizeof(resp),
|
||||||
|
};
|
||||||
|
struct msghdr msg = {
|
||||||
|
.msg_name = NULL,
|
||||||
|
.msg_namelen = 0,
|
||||||
|
.msg_iov = &iov,
|
||||||
|
.msg_iovlen = 1,
|
||||||
|
.msg_control = cred_buffer,
|
||||||
|
.msg_controllen = sizeof(cred_buffer),
|
||||||
|
.msg_flags = 0,
|
||||||
|
};
|
||||||
|
|
||||||
memset(&iov, 0, sizeof(iov));
|
assert(fd >= 0);
|
||||||
iov.iov_base = &resp;
|
assert(list);
|
||||||
iov.iov_len = sizeof(resp);
|
|
||||||
|
|
||||||
memset(&msg, 0, sizeof(msg));
|
|
||||||
msg.msg_name = NULL;
|
|
||||||
msg.msg_namelen = 0;
|
|
||||||
msg.msg_iov = &iov;
|
|
||||||
msg.msg_iovlen = 1;
|
|
||||||
msg.msg_control = cred_buffer;
|
|
||||||
msg.msg_controllen = sizeof(cred_buffer);
|
|
||||||
msg.msg_flags = 0;
|
|
||||||
|
|
||||||
bytes = recvmsg(fd, &msg, 0);
|
bytes = recvmsg(fd, &msg, 0);
|
||||||
if (bytes < 0) {
|
if (bytes < 0)
|
||||||
r = -errno;
|
return -errno;
|
||||||
goto finish;
|
|
||||||
}
|
|
||||||
|
|
||||||
cmsg = CMSG_FIRSTHDR(&msg);
|
cmsg = CMSG_FIRSTHDR(&msg);
|
||||||
if (!cmsg || cmsg->cmsg_type != SCM_CREDENTIALS) {
|
if (!cmsg || cmsg->cmsg_type != SCM_CREDENTIALS)
|
||||||
r = -EIO;
|
return -EIO;
|
||||||
goto finish;
|
|
||||||
}
|
|
||||||
|
|
||||||
ucred = (struct ucred*) CMSG_DATA(cmsg);
|
ucred = (struct ucred*) CMSG_DATA(cmsg);
|
||||||
if (ucred->uid != 0 || ucred->pid != 0)
|
if (ucred->uid != 0 || ucred->pid != 0)
|
||||||
continue;
|
return 0;
|
||||||
|
|
||||||
for (p = &resp.hdr; bytes > 0; p = NLMSG_NEXT(p, bytes)) {
|
for (p = &resp.hdr; bytes > 0; p = NLMSG_NEXT(p, bytes)) {
|
||||||
struct ifaddrmsg *ifaddrmsg;
|
struct ifaddrmsg *ifaddrmsg;
|
||||||
@ -121,25 +86,20 @@ int ifconf_acquire_addresses(struct address **_list, unsigned *_n_list) {
|
|||||||
size_t l;
|
size_t l;
|
||||||
void *local = NULL, *address = NULL;
|
void *local = NULL, *address = NULL;
|
||||||
|
|
||||||
if (!NLMSG_OK(p, (size_t) bytes)) {
|
if (!NLMSG_OK(p, (size_t) bytes))
|
||||||
r = -EIO;
|
return -EIO;
|
||||||
goto finish;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p->nlmsg_seq != seq)
|
if (p->nlmsg_seq != SEQ)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (p->nlmsg_type == NLMSG_DONE) {
|
if (p->nlmsg_type == NLMSG_DONE)
|
||||||
r = 0;
|
return 1;
|
||||||
goto finish;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p->nlmsg_type == NLMSG_ERROR) {
|
if (p->nlmsg_type == NLMSG_ERROR) {
|
||||||
struct nlmsgerr *nlmsgerr;
|
struct nlmsgerr *nlmsgerr;
|
||||||
|
|
||||||
nlmsgerr = NLMSG_DATA(p);
|
nlmsgerr = NLMSG_DATA(p);
|
||||||
r = -nlmsgerr->error;
|
return -nlmsgerr->error;
|
||||||
goto finish;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p->nlmsg_type != RTM_NEWADDR)
|
if (p->nlmsg_type != RTM_NEWADDR)
|
||||||
@ -177,32 +137,66 @@ int ifconf_acquire_addresses(struct address **_list, unsigned *_n_list) {
|
|||||||
if (!address)
|
if (!address)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
list = realloc(list, (n_list+1) * sizeof(struct address));
|
*list = realloc(*list, (*n_list+1) * sizeof(struct address));
|
||||||
if (!list) {
|
if (!*list)
|
||||||
r = -ENOMEM;
|
return -ENOMEM;
|
||||||
goto finish;
|
|
||||||
|
(*list)[*n_list].family = ifaddrmsg->ifa_family;
|
||||||
|
(*list)[*n_list].scope = ifaddrmsg->ifa_scope;
|
||||||
|
memcpy((*list)[*n_list].address,
|
||||||
|
address, ifaddrmsg->ifa_family == AF_INET ? 4 : 16);
|
||||||
|
(*list)[*n_list].ifindex = ifaddrmsg->ifa_index;
|
||||||
|
|
||||||
|
(*n_list)++;
|
||||||
}
|
}
|
||||||
|
|
||||||
list[n_list].family = ifaddrmsg->ifa_family;
|
return 0;
|
||||||
list[n_list].scope = ifaddrmsg->ifa_scope;
|
|
||||||
memcpy(list[n_list].address, address, ifaddrmsg->ifa_family == AF_INET ? 4 : 16);
|
|
||||||
list[n_list].ifindex = ifaddrmsg->ifa_index;
|
|
||||||
|
|
||||||
n_list++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
finish:
|
|
||||||
close(fd);
|
|
||||||
|
|
||||||
if (r < 0)
|
int ifconf_acquire_addresses(struct address **_list, unsigned *_n_list) {
|
||||||
|
|
||||||
|
struct {
|
||||||
|
struct nlmsghdr hdr;
|
||||||
|
struct rtgenmsg gen;
|
||||||
|
} req = { {
|
||||||
|
.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg)),
|
||||||
|
.nlmsg_type = RTM_GETADDR,
|
||||||
|
.nlmsg_flags = NLM_F_REQUEST|NLM_F_DUMP|NLM_F_ACK,
|
||||||
|
.nlmsg_seq = SEQ,
|
||||||
|
.nlmsg_pid = 0,
|
||||||
|
}, {
|
||||||
|
.rtgen_family = AF_UNSPEC,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
int r, on = 1;
|
||||||
|
struct address *list = NULL;
|
||||||
|
unsigned n_list = 0;
|
||||||
|
int _cleanup_close_ fd;
|
||||||
|
|
||||||
|
fd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
|
||||||
|
if (fd < 0)
|
||||||
|
return -errno;
|
||||||
|
|
||||||
|
if (setsockopt(fd, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)) < 0)
|
||||||
|
return -errno;
|
||||||
|
|
||||||
|
if (send(fd, &req, req.hdr.nlmsg_len, 0) < 0)
|
||||||
|
return -errno;
|
||||||
|
|
||||||
|
while((r = read_reply(fd, &list, &n_list)) == 0)
|
||||||
|
;
|
||||||
|
|
||||||
|
if (r < 0) {
|
||||||
free(list);
|
free(list);
|
||||||
else {
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(n_list == 0 || list);
|
||||||
qsort(list, n_list, sizeof(struct address), address_compare);
|
qsort(list, n_list, sizeof(struct address), address_compare);
|
||||||
|
|
||||||
*_list = list;
|
*_list = list;
|
||||||
*_n_list = n_list;
|
*_n_list = n_list;
|
||||||
}
|
|
||||||
|
|
||||||
return r;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user