netlink: refactor error numbers from netlink
Originally, these were error numbers from libnl3. These error numbers are separate from errno, which is unfortunate, because sometimes we care about the native errno returned from kernel. Now, refactor them so that the error numbers are in the shared realm of errno, but failures from kernel or underlying API are still returned via their native errno. - NLE_INVAL doesn't exist anymore. Passing invalid arguments to a function is commonly a bug. g_return_*(NLE_BUG) is the right answer to that. - NLE_NOMEM and NLE_AGAIN is replaced by their errno counterparts. - drop several error numbers. If nobody cares about these numbers, there is no reason to have a specific error number for them. NLE_UNSPEC is sufficient.
This commit is contained in:
@@ -80,10 +80,6 @@ enum {
|
||||
|
||||
#define VLAN_FLAG_MVRP 0x8
|
||||
|
||||
/* nm-internal error codes for libnl. Make sure they don't overlap. */
|
||||
#define _NLE_NM_NOBUFS 500
|
||||
#define _NLE_MSG_TRUNC 501
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#define IFQDISCSIZ 32
|
||||
@@ -6496,19 +6492,19 @@ continue_reading:
|
||||
if (!handle_events)
|
||||
goto continue_reading;
|
||||
}
|
||||
n = -_NLE_MSG_TRUNC;
|
||||
n = -NLE_USER_MSG_TRUNC;
|
||||
break;
|
||||
}
|
||||
case -ENOBUFS:
|
||||
n = -_NLE_NM_NOBUFS;
|
||||
n = -NLE_USER_NOBUFS;
|
||||
break;
|
||||
case -NLE_NOMEM:
|
||||
case -ENOMEM:
|
||||
if (errno == ENOBUFS) {
|
||||
/* we are very much interested in a overrun of the receive buffer.
|
||||
* nl_recv() maps all kinds of errors to NLE_NOMEM, so check also
|
||||
* nl_recv() maps all kinds of errors to ENOMEM, so check also
|
||||
* for errno explicitly. And if so, hack our own return code to signal
|
||||
* the overrun. */
|
||||
n = -_NLE_NM_NOBUFS;
|
||||
n = -NLE_USER_NOBUFS;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -6526,7 +6522,7 @@ continue_reading:
|
||||
|
||||
msg = nlmsg_convert (hdr);
|
||||
if (!msg) {
|
||||
err = -NLE_NOMEM;
|
||||
err = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -6686,19 +6682,19 @@ event_handler_read_netlink (NMPlatform *platform, gboolean wait_for_acks)
|
||||
|
||||
if (nle < 0) {
|
||||
switch (nle) {
|
||||
case -NLE_AGAIN:
|
||||
case -EAGAIN:
|
||||
goto after_read;
|
||||
case -NLE_DUMP_INTR:
|
||||
_LOGD ("netlink: read: uncritical failure to retrieve incoming events: %s (%d)", nl_geterror (nle), nle);
|
||||
break;
|
||||
case -_NLE_MSG_TRUNC:
|
||||
case -_NLE_NM_NOBUFS:
|
||||
case -NLE_USER_MSG_TRUNC:
|
||||
case -NLE_USER_NOBUFS:
|
||||
_LOGI ("netlink: read: %s. Need to resynchronize platform cache",
|
||||
({
|
||||
const char *_reason = "unknown";
|
||||
switch (nle) {
|
||||
case -_NLE_MSG_TRUNC: _reason = "message truncated"; break;
|
||||
case -_NLE_NM_NOBUFS: _reason = "too many netlink events"; break;
|
||||
case -NLE_USER_MSG_TRUNC: _reason = "message truncated"; break;
|
||||
case -NLE_USER_NOBUFS: _reason = "too many netlink events"; break;
|
||||
}
|
||||
_reason;
|
||||
}));
|
||||
|
@@ -65,6 +65,40 @@ struct nl_sock {
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
NM_UTILS_LOOKUP_STR_DEFINE_STATIC (_geterror, int,
|
||||
NM_UTILS_LOOKUP_DEFAULT (NULL),
|
||||
NM_UTILS_LOOKUP_ITEM (NLE_UNSPEC, "NLE_UNSPEC"),
|
||||
NM_UTILS_LOOKUP_ITEM (NLE_BUG, "NLE_BUG"),
|
||||
NM_UTILS_LOOKUP_ITEM (NLE_NATIVE_ERRNO, "NLE_NATIVE_ERRNO"),
|
||||
|
||||
NM_UTILS_LOOKUP_ITEM (NLE_ATTRSIZE, "NLE_ATTRSIZE"),
|
||||
NM_UTILS_LOOKUP_ITEM (NLE_BAD_SOCK, "NLE_BAD_SOCK"),
|
||||
NM_UTILS_LOOKUP_ITEM (NLE_DUMP_INTR, "NLE_DUMP_INTR"),
|
||||
NM_UTILS_LOOKUP_ITEM (NLE_MSG_OVERFLOW, "NLE_MSG_OVERFLOW"),
|
||||
NM_UTILS_LOOKUP_ITEM (NLE_MSG_TOOSHORT, "NLE_MSG_TOOSHORT"),
|
||||
NM_UTILS_LOOKUP_ITEM (NLE_MSG_TRUNC, "NLE_MSG_TRUNC"),
|
||||
NM_UTILS_LOOKUP_ITEM (NLE_SEQ_MISMATCH, "NLE_SEQ_MISMATCH"),
|
||||
NM_UTILS_LOOKUP_ITEM (NLE_USER_NOBUFS, "NLE_USER_NOBUFS"),
|
||||
NM_UTILS_LOOKUP_ITEM (NLE_USER_MSG_TRUNC, "NLE_USER_MSG_TRUNC"),
|
||||
)
|
||||
|
||||
const char *
|
||||
nl_geterror (int err)
|
||||
{
|
||||
const char *s;
|
||||
|
||||
err = nl_errno (err);
|
||||
|
||||
if (err >= _NLE_BASE) {
|
||||
s = _geterror (err);
|
||||
if (s)
|
||||
return s;
|
||||
}
|
||||
return g_strerror (err);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
NM_UTILS_ENUM2STR_DEFINE (nl_nlmsgtype2str, int,
|
||||
NM_UTILS_ENUM2STR (NLMSG_NOOP, "NOOP"),
|
||||
NM_UTILS_ENUM2STR (NLMSG_ERROR, "ERROR"),
|
||||
@@ -365,7 +399,7 @@ nlmsg_append (struct nl_msg *n, void *data, size_t len, int pad)
|
||||
|
||||
tmp = nlmsg_reserve(n, len, pad);
|
||||
if (tmp == NULL)
|
||||
return -NLE_NOMEM;
|
||||
return -ENOMEM;
|
||||
|
||||
memcpy(tmp, data, len);
|
||||
return 0;
|
||||
@@ -456,9 +490,9 @@ nla_put (struct nl_msg *msg, int attrtype, int datalen, const void *data)
|
||||
nla = nla_reserve(msg, attrtype, datalen);
|
||||
if (!nla) {
|
||||
if (datalen < 0)
|
||||
return -NLE_INVAL;
|
||||
g_return_val_if_reached (-NLE_BUG);
|
||||
|
||||
return -NLE_NOMEM;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (datalen > 0)
|
||||
@@ -579,15 +613,15 @@ validate_nla (const struct nlattr *nla, int maxtype,
|
||||
minlen = nla_attr_minlen[pt->type];
|
||||
|
||||
if (nla_len(nla) < minlen)
|
||||
return -NLE_RANGE;
|
||||
return -NLE_UNSPEC;
|
||||
|
||||
if (pt->maxlen && nla_len(nla) > pt->maxlen)
|
||||
return -NLE_RANGE;
|
||||
return -NLE_UNSPEC;
|
||||
|
||||
if (pt->type == NLA_STRING) {
|
||||
const char *data = nla_data(nla);
|
||||
if (data[nla_len(nla) - 1] != '\0')
|
||||
return -NLE_INVAL;
|
||||
return -NLE_UNSPEC;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -876,7 +910,7 @@ nl_cb_err (struct nl_cb *cb, enum nl_cb_kind kind,
|
||||
nl_recvmsg_err_cb_t func, void *arg)
|
||||
{
|
||||
if ((unsigned int) kind > NL_CB_KIND_MAX)
|
||||
return -NLE_RANGE;
|
||||
g_return_val_if_reached (-NLE_BUG);
|
||||
|
||||
if (kind == NL_CB_CUSTOM) {
|
||||
cb->cb_err = func;
|
||||
@@ -894,10 +928,10 @@ nl_cb_set (struct nl_cb *cb, enum nl_cb_type type, enum nl_cb_kind kind,
|
||||
nl_recvmsg_msg_cb_t func, void *arg)
|
||||
{
|
||||
if ((unsigned int) type > NL_CB_TYPE_MAX)
|
||||
return -NLE_RANGE;
|
||||
g_return_val_if_reached (-NLE_BUG);
|
||||
|
||||
if ((unsigned int) kind > NL_CB_KIND_MAX)
|
||||
return -NLE_RANGE;
|
||||
g_return_val_if_reached (-NLE_BUG);
|
||||
|
||||
if (kind == NL_CB_CUSTOM) {
|
||||
cb->cb_set[type] = func;
|
||||
@@ -993,10 +1027,10 @@ nl_socket_set_passcred (struct nl_sock *sk, int state)
|
||||
if (sk->s_fd == -1)
|
||||
return -NLE_BAD_SOCK;
|
||||
|
||||
err = setsockopt(sk->s_fd, SOL_SOCKET, SO_PASSCRED,
|
||||
&state, sizeof(state));
|
||||
err = setsockopt (sk->s_fd, SOL_SOCKET, SO_PASSCRED,
|
||||
&state, sizeof(state));
|
||||
if (err < 0)
|
||||
return -errno;
|
||||
return -nl_syserr2nlerr (errno);
|
||||
|
||||
if (state)
|
||||
sk->s_flags |= NL_SOCK_PASSCRED;
|
||||
@@ -1027,7 +1061,7 @@ nl_socket_set_nonblocking (const struct nl_sock *sk)
|
||||
return -NLE_BAD_SOCK;
|
||||
|
||||
if (fcntl(sk->s_fd, F_SETFL, O_NONBLOCK) < 0)
|
||||
return -errno;
|
||||
return -nl_syserr2nlerr (errno);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1049,13 +1083,13 @@ nl_socket_set_buffer_size (struct nl_sock *sk, int rxbuf, int txbuf)
|
||||
err = setsockopt (sk->s_fd, SOL_SOCKET, SO_SNDBUF,
|
||||
&txbuf, sizeof(txbuf));
|
||||
if (err < 0) {
|
||||
return -errno;
|
||||
return -nl_syserr2nlerr (errno);
|
||||
}
|
||||
|
||||
err = setsockopt (sk->s_fd, SOL_SOCKET, SO_RCVBUF,
|
||||
&rxbuf, sizeof(rxbuf));
|
||||
if (err < 0) {
|
||||
return -errno;
|
||||
return -nl_syserr2nlerr (errno);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -1075,14 +1109,14 @@ nl_socket_add_memberships (struct nl_sock *sk, int group, ...)
|
||||
while (group != 0) {
|
||||
if (group < 0) {
|
||||
va_end(ap);
|
||||
return -NLE_INVAL;
|
||||
g_return_val_if_reached (-NLE_BUG);
|
||||
}
|
||||
|
||||
err = setsockopt (sk->s_fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP,
|
||||
&group, sizeof(group));
|
||||
if (err < 0) {
|
||||
va_end(ap);
|
||||
return -errno;
|
||||
return -nl_syserr2nlerr (errno);
|
||||
}
|
||||
|
||||
group = va_arg(ap, int);
|
||||
@@ -1111,7 +1145,7 @@ nl_connect (struct nl_sock *sk, int protocol)
|
||||
|
||||
sk->s_fd = socket (AF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, protocol);
|
||||
if (sk->s_fd < 0) {
|
||||
err = -errno;
|
||||
err = -nl_syserr2nlerr (errno);
|
||||
goto errout;
|
||||
}
|
||||
|
||||
@@ -1124,7 +1158,7 @@ nl_connect (struct nl_sock *sk, int protocol)
|
||||
err = bind (sk->s_fd, (struct sockaddr*) &sk->s_local,
|
||||
sizeof(sk->s_local));
|
||||
if (err != 0) {
|
||||
err = -errno;
|
||||
err = -nl_syserr2nlerr (errno);
|
||||
goto errout;
|
||||
}
|
||||
|
||||
@@ -1132,17 +1166,17 @@ nl_connect (struct nl_sock *sk, int protocol)
|
||||
err = getsockname (sk->s_fd, (struct sockaddr *) &local,
|
||||
&addrlen);
|
||||
if (err < 0) {
|
||||
err = -errno;
|
||||
err = -nl_syserr2nlerr (errno);
|
||||
goto errout;
|
||||
}
|
||||
|
||||
if (addrlen != sizeof(local)) {
|
||||
err = -NLE_NOADDR;
|
||||
err = -NLE_UNSPEC;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
if (local.nl_family != AF_NETLINK) {
|
||||
err = -NLE_AF_NOSUPPORT;
|
||||
err = -NLE_UNSPEC;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
@@ -1150,12 +1184,12 @@ nl_connect (struct nl_sock *sk, int protocol)
|
||||
sk->s_proto = protocol;
|
||||
|
||||
return 0;
|
||||
|
||||
errout:
|
||||
if (sk->s_fd != -1) {
|
||||
close(sk->s_fd);
|
||||
sk->s_fd = -1;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -1174,7 +1208,7 @@ nl_wait_for_ack(struct nl_sock *sk)
|
||||
|
||||
cb = nl_cb_clone(sk->s_cb);
|
||||
if (cb == NULL)
|
||||
return -NLE_NOMEM;
|
||||
return -ENOMEM;
|
||||
|
||||
nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_wait_handler, NULL);
|
||||
err = nl_recvmsgs(sk, cb);
|
||||
@@ -1229,7 +1263,7 @@ continue_reading:
|
||||
nlmsg_free(msg);
|
||||
msg = nlmsg_convert(hdr);
|
||||
if (!msg) {
|
||||
err = -NLE_NOMEM;
|
||||
err = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -1441,7 +1475,7 @@ nl_sendmsg (struct nl_sock *sk, struct nl_msg *msg, struct msghdr *hdr)
|
||||
|
||||
ret = sendmsg(sk->s_fd, hdr, 0);
|
||||
if (ret < 0)
|
||||
return -errno;
|
||||
return -nl_syserr2nlerr (errno);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -1547,7 +1581,7 @@ nl_recv (struct nl_sock *sk, struct sockaddr_nl *nla,
|
||||
int retval = 0;
|
||||
|
||||
if (!buf || !nla)
|
||||
return -NLE_INVAL;
|
||||
g_return_val_if_reached (-NLE_BUG);
|
||||
|
||||
if ( (sk->s_flags & NL_MSG_PEEK)
|
||||
|| (!(sk->s_flags & NL_MSG_PEEK_EXPLICIT) && sk->s_bufsize == 0))
|
||||
@@ -1560,7 +1594,7 @@ nl_recv (struct nl_sock *sk, struct sockaddr_nl *nla,
|
||||
iov.iov_base = malloc(iov.iov_len);
|
||||
|
||||
if (!iov.iov_base) {
|
||||
retval = -NLE_NOMEM;
|
||||
retval = -ENOMEM;
|
||||
goto abort;
|
||||
}
|
||||
|
||||
@@ -1568,7 +1602,7 @@ nl_recv (struct nl_sock *sk, struct sockaddr_nl *nla,
|
||||
msg.msg_controllen = CMSG_SPACE(sizeof(struct ucred));
|
||||
msg.msg_control = malloc(msg.msg_controllen);
|
||||
if (!msg.msg_control) {
|
||||
retval = -NLE_NOMEM;
|
||||
retval = -ENOMEM;
|
||||
goto abort;
|
||||
}
|
||||
}
|
||||
@@ -1583,7 +1617,7 @@ retry:
|
||||
if (errno == EINTR)
|
||||
goto retry;
|
||||
|
||||
retval = -errno;
|
||||
retval = -nl_syserr2nlerr (errno);
|
||||
goto abort;
|
||||
}
|
||||
|
||||
@@ -1598,7 +1632,7 @@ retry:
|
||||
msg.msg_controllen *= 2;
|
||||
tmp = realloc(msg.msg_control, msg.msg_controllen);
|
||||
if (!tmp) {
|
||||
retval = -NLE_NOMEM;
|
||||
retval = -ENOMEM;
|
||||
goto abort;
|
||||
}
|
||||
msg.msg_control = tmp;
|
||||
@@ -1620,7 +1654,7 @@ retry:
|
||||
iov.iov_len = n;
|
||||
tmp = realloc(iov.iov_base, iov.iov_len);
|
||||
if (!tmp) {
|
||||
retval = -NLE_NOMEM;
|
||||
retval = -ENOMEM;
|
||||
goto abort;
|
||||
}
|
||||
iov.iov_base = tmp;
|
||||
@@ -1635,7 +1669,7 @@ retry:
|
||||
}
|
||||
|
||||
if (msg.msg_namelen != sizeof(struct sockaddr_nl)) {
|
||||
retval = -NLE_NOADDR;
|
||||
retval = -NLE_UNSPEC;
|
||||
goto abort;
|
||||
}
|
||||
|
||||
@@ -1649,7 +1683,7 @@ retry:
|
||||
continue;
|
||||
tmpcreds = malloc(sizeof(*tmpcreds));
|
||||
if (!tmpcreds) {
|
||||
retval = -NLE_NOMEM;
|
||||
retval = -ENOMEM;
|
||||
goto abort;
|
||||
}
|
||||
memcpy(tmpcreds, CMSG_DATA(cmsg), sizeof(*tmpcreds));
|
||||
|
@@ -27,44 +27,54 @@
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#define NLE_AGAIN EAGAIN
|
||||
#define NLE_NOMEM ENOMEM
|
||||
#define NLE_BAD_SOCK EBADF
|
||||
#define NLE_INVAL EINVAL
|
||||
#define NLE_RANGE ERANGE
|
||||
#define NLE_OBJ_NOTFOUND ENOENT
|
||||
#define NLE_NOADDR EADDRNOTAVAIL
|
||||
#define NLE_MSG_OVERFLOW EOVERFLOW
|
||||
#define NLE_AF_NOSUPPORT EAFNOSUPPORT
|
||||
#define _NLE_BASE 100000
|
||||
#define NLE_UNSPEC (_NLE_BASE + 0)
|
||||
#define NLE_BUG (_NLE_BASE + 1)
|
||||
#define NLE_NATIVE_ERRNO (_NLE_BASE + 2)
|
||||
#define NLE_SEQ_MISMATCH (_NLE_BASE + 3)
|
||||
#define NLE_MSG_TRUNC (_NLE_BASE + 4)
|
||||
#define NLE_MSG_TOOSHORT (_NLE_BASE + 5)
|
||||
#define NLE_DUMP_INTR (_NLE_BASE + 6)
|
||||
#define NLE_ATTRSIZE (_NLE_BASE + 7)
|
||||
#define NLE_BAD_SOCK (_NLE_BASE + 8)
|
||||
#define NLE_NOADDR (_NLE_BASE + 12)
|
||||
#define NLE_MSG_OVERFLOW (_NLE_BASE + 13)
|
||||
|
||||
#define NLE_SEQ_MISMATCH 10016
|
||||
#define NLE_MSG_TRUNC 10018
|
||||
#define NLE_MSG_TOOSHORT 10021
|
||||
#define NLE_DUMP_INTR 10033
|
||||
#define NLE_ATTRSIZE 10034
|
||||
#define NLE_BUG 19000
|
||||
/* user errors, these errors are never returned by netlink functions themself,
|
||||
* but are reserved for other components. */
|
||||
#define NLE_USER_NOBUFS (_NLE_BASE + 15)
|
||||
#define NLE_USER_MSG_TRUNC (_NLE_BASE + 16)
|
||||
|
||||
#define _NLE_BASE_END (_NLE_BASE + 17)
|
||||
|
||||
static inline int
|
||||
nl_errno (int error)
|
||||
nl_errno (int err)
|
||||
{
|
||||
/* the error codes from our netlink implementation are plain errno.
|
||||
* However, often we encode them as negative values.
|
||||
/* the error codes from our netlink implementation are plain errno
|
||||
* extended with our own error in a particular range starting from
|
||||
* _NLE_BASE.
|
||||
*
|
||||
* A negative errno is the same as it's positive counterpart.
|
||||
*
|
||||
* This function normalizes the error code and always returns a
|
||||
* non-negative value. */
|
||||
return error >= 0
|
||||
? error
|
||||
: ((error == G_MININT) ? NLE_BUG : -errno);
|
||||
* However, often we encode errors as negative values. This function
|
||||
* normalizes the error and returns it's positive value. */
|
||||
return err >= 0
|
||||
? err
|
||||
: ((err == G_MININT) ? NLE_BUG : -errno);
|
||||
}
|
||||
|
||||
static inline const char *
|
||||
nl_geterror (int error)
|
||||
static inline int
|
||||
nl_syserr2nlerr (int err)
|
||||
{
|
||||
return g_strerror (nl_errno (error));
|
||||
if (err == G_MININT)
|
||||
return NLE_NATIVE_ERRNO;
|
||||
if (err < 0)
|
||||
err = -err;
|
||||
return (err >= _NLE_BASE && err < _NLE_BASE_END)
|
||||
? NLE_NATIVE_ERRNO
|
||||
: err;
|
||||
}
|
||||
|
||||
const char *nl_geterror (int err);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* Basic attribute data types */
|
||||
|
@@ -82,7 +82,7 @@ genl_ctrl_resolve (struct nl_sock *sk, const char *name)
|
||||
struct nl_msg *msg;
|
||||
struct nl_cb *cb, *orig;
|
||||
int rc;
|
||||
int result = -NLE_OBJ_NOTFOUND;
|
||||
int result = -ENOENT;
|
||||
gint32 response_data = -1;
|
||||
|
||||
if (!(orig = nl_socket_get_cb (sk)))
|
||||
@@ -235,7 +235,7 @@ _nl80211_send_and_recv (struct nl_sock *nl_sock,
|
||||
*/
|
||||
while (!done) {
|
||||
err = nl_recvmsgs (nl_sock, cb);
|
||||
if (err && err != -NLE_AGAIN) {
|
||||
if (err < 0 && err != -EAGAIN) {
|
||||
/* Kernel scan list can change while we are dumping it, as new scan
|
||||
* results from H/W can arrive. BSS info is assured to be consistent
|
||||
* and we don't need consistent view of whole scan list. Hence do
|
||||
|
Reference in New Issue
Block a user