This commit is contained in:
Thomas Graf 2012-10-22 12:24:19 +02:00
commit 785f810b95
8 changed files with 101 additions and 52 deletions

View file

@ -96,10 +96,10 @@ static void family_dump_line(struct nl_object *obj, struct nl_dump_params *p)
}
static const struct trans_tbl ops_flags[] = {
__ADD(GENL_ADMIN_PERM, admin-perm)
__ADD(GENL_CMD_CAP_DO, has-doit)
__ADD(GENL_CMD_CAP_DUMP, has-dump)
__ADD(GENL_CMD_CAP_HASPOL, has-policy)
__ADD(GENL_ADMIN_PERM, admin_perm)
__ADD(GENL_CMD_CAP_DO, has_doit)
__ADD(GENL_CMD_CAP_DUMP, has_dump)
__ADD(GENL_CMD_CAP_HASPOL, has_policy)
};
static char *ops_flags2str(int flags, char *buf, size_t len)

121
lib/nl.c
View file

@ -405,9 +405,9 @@ errout:
/**
* Receive data from netlink socket
* @arg sk Netlink socket.
* @arg nla Destination pointer for peer's netlink address.
* @arg buf Destination pointer for message content.
* @arg creds Destination pointer for credentials.
* @arg nla Destination pointer for peer's netlink address. (required)
* @arg buf Destination pointer for message content. (required)
* @arg creds Destination pointer for credentials. (optional)
*
* Receives a netlink message, allocates a buffer in \c *buf and
* stores the message content. The peer's netlink address is stored
@ -433,13 +433,9 @@ int nl_recv(struct nl_sock *sk, struct sockaddr_nl *nla,
.msg_namelen = sizeof(struct sockaddr_nl),
.msg_iov = &iov,
.msg_iovlen = 1,
.msg_control = NULL,
.msg_controllen = 0,
.msg_flags = 0,
};
struct cmsghdr *cmsg;
memset(nla, 0, sizeof(*nla));
struct ucred* tmpcreds = NULL;
int retval = 0;
if (sk->s_flags & NL_MSG_PEEK)
flags |= MSG_PEEK | MSG_TRUNC;
@ -448,73 +444,114 @@ int nl_recv(struct nl_sock *sk, struct sockaddr_nl *nla,
page_size = getpagesize();
iov.iov_len = sk->s_bufsize ? : page_size;
iov.iov_base = *buf = malloc(iov.iov_len);
iov.iov_base = malloc(iov.iov_len);
if (sk->s_flags & NL_SOCK_PASSCRED) {
if (!iov.iov_base) {
retval = -NLE_NOMEM;
goto abort;
}
if (creds && (sk->s_flags & NL_SOCK_PASSCRED)) {
msg.msg_controllen = CMSG_SPACE(sizeof(struct ucred));
msg.msg_control = calloc(1, msg.msg_controllen);
msg.msg_control = malloc(msg.msg_controllen);
if (!msg.msg_control) {
retval = -NLE_NOMEM;
goto abort;
}
}
retry:
n = recvmsg(sk->s_fd, &msg, flags);
if (!n)
if (!n) {
retval = 0;
goto abort;
else if (n < 0) {
}
if (n < 0) {
if (errno == EINTR) {
NL_DBG(3, "recvmsg() returned EINTR, retrying\n");
goto retry;
} else if (errno == EAGAIN) {
NL_DBG(3, "recvmsg() returned EAGAIN, aborting\n");
goto abort;
} else {
free(msg.msg_control);
free(*buf);
return -nl_syserr2nlerr(errno);
}
if (errno == EAGAIN || errno == EWOULDBLOCK) {
NL_DBG(3, "recvmsg() returned EAGAIN||EWOULDBLOCK, aborting\n");
retval = 0;
goto abort;
}
retval = -nl_syserr2nlerr(errno);
goto abort;
}
if (msg.msg_flags & MSG_CTRUNC) {
void *tmp;
msg.msg_controllen *= 2;
msg.msg_control = realloc(msg.msg_control, msg.msg_controllen);
tmp = realloc(msg.msg_control, msg.msg_controllen);
if (!tmp) {
retval = -NLE_NOMEM;
goto abort;
}
msg.msg_control = tmp;
goto retry;
} else if (iov.iov_len < n || msg.msg_flags & MSG_TRUNC) {
}
if (iov.iov_len < n || (msg.msg_flags & MSG_TRUNC)) {
void *tmp;
/* Provided buffer is not long enough, enlarge it
* to size of n (which should be total length of the message)
* and try again. */
iov.iov_len = n;
iov.iov_base = *buf = realloc(*buf, iov.iov_len);
tmp = realloc(iov.iov_base, iov.iov_len);
if (!tmp) {
retval = -NLE_NOMEM;
goto abort;
}
iov.iov_base = tmp;
flags = 0;
goto retry;
} else if (flags != 0) {
}
if (flags != 0) {
/* Buffer is big enough, do the actual reading */
flags = 0;
goto retry;
}
if (msg.msg_namelen != sizeof(struct sockaddr_nl)) {
free(msg.msg_control);
free(*buf);
return -NLE_NOADDR;
retval = -NLE_NOADDR;
goto abort;
}
for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
if (cmsg->cmsg_level == SOL_SOCKET &&
cmsg->cmsg_type == SCM_CREDENTIALS) {
if (creds) {
*creds = calloc(1, sizeof(struct ucred));
memcpy(*creds, CMSG_DATA(cmsg), sizeof(struct ucred));
if (creds && (sk->s_flags & NL_SOCK_PASSCRED)) {
struct cmsghdr *cmsg;
for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
if (cmsg->cmsg_level != SOL_SOCKET)
continue;
if (cmsg->cmsg_type != SCM_CREDENTIALS)
continue;
tmpcreds = malloc(sizeof(*tmpcreds));
if (!tmpcreds) {
retval = -NLE_NOMEM;
goto abort;
}
memcpy(tmpcreds, CMSG_DATA(cmsg), sizeof(*tmpcreds));
break;
}
}
free(msg.msg_control);
return n;
retval = n;
abort:
free(msg.msg_control);
free(*buf);
return 0;
if (retval <= 0) {
free(iov.iov_base); iov.iov_base = NULL;
free(tmpcreds); tmpcreds = NULL;
}
*buf = iov.iov_base;
if (creds)
*creds = tmpcreds;
return retval;
}
/** @cond SKIP */
@ -540,6 +577,12 @@ static int recvmsgs(struct nl_sock *sk, struct nl_cb *cb)
int n, err = 0, multipart = 0, interrupted = 0, nrecv = 0;
unsigned char *buf = NULL;
struct nlmsghdr *hdr;
/*
nla is passed on to not only to nl_recv() but may also be passed
to a function pointer provided by the caller which may or may not
initialize the variable. Thomas Graf.
*/
struct sockaddr_nl nla = {0};
struct nl_msg *msg = NULL;
struct ucred *creds = NULL;

View file

@ -311,7 +311,7 @@ static int classid_map_add(uint32_t classid, const char *name)
int rtnl_tc_read_classid_file(void)
{
static time_t last_read;
struct stat st = {0};
struct stat st;
char buf[256], *path;
FILE *fd;
int err;

View file

@ -14,8 +14,14 @@
#include <netlink/netlink.h>
#include <netlink/route/cls/ematch.h>
static int container_parse(struct rtnl_ematch *e, void *data, size_t len)
static int container_parse(struct rtnl_ematch *e, void *data, size_t len __attribute__((unused)))
{
/*
The kernel may provide more than 4 bytes of data in the future and we want
older libnl versions to be ok with that. We want interfaces to be growable
so we only ever enforce a minimum data length and copy as much as we are
aware of. Thomas Graf.
*/
memcpy(e->e_data, data, sizeof(uint32_t));
return 0;

View file

@ -90,7 +90,7 @@ static int read_pktlocs(void)
YY_BUFFER_STATE buf = NULL;
yyscan_t scanner = NULL;
static time_t last_read;
struct stat st = {0};
struct stat st;
char *path;
int i, err;
FILE *fd;

View file

@ -190,10 +190,10 @@ static int htb_qdisc_msg_fill(struct rtnl_tc *tc, void *data,
struct nl_msg *msg)
{
struct rtnl_htb_qdisc *htb = data;
struct tc_htb_glob opts = {0};
opts.version = TC_HTB_PROTOVER;
opts.rate2quantum = 10;
struct tc_htb_glob opts = {
.version = TC_HTB_PROTOVER,
.rate2quantum = 10,
};
if (htb) {
if (htb->qh_mask & SCH_HTB_HAS_RATE2QUANTUM)

View file

@ -332,7 +332,7 @@ static int route_compare(struct nl_object *_a, struct nl_object *_b,
if (a->rt_metrics_mask & (1 << i) &&
(!(b->rt_metrics_mask & (1 << i)) ||
a->rt_metrics[i] != b->rt_metrics[i]))
ROUTE_DIFF(METRICS, 1);
diff |= ROUTE_DIFF(METRICS, 1);
}
diff |= ROUTE_DIFF(FLAGS,

View file

@ -96,7 +96,7 @@ int main(int argc, char *argv[])
copy_range = 0xFFFF;
if (argc > 4)
copy_mode = atoi(argv[4]);
copy_range = atoi(argv[4]);
nfnl_log_set_copy_range(log, copy_range);
if ((err = nfnl_log_create(nf_sock, log)) < 0)