libcasper: Fix inconsistent error codes of cap_get{addr,name}info()
The get{addr,name}info(3) API is designed to return an API-specific error
code that is independent of errno. The cap_get{addr,name}info() functions
returned either an errno or API-specific error code inconsistently.
This change fixes this mismatch.
When the API returns an errno, the return value itself is set to
EAI_SYSTEM and errno is set depending on the actual error. So, usually
this API is called in the following form:
error = getnameinfo(...);
if (error == EAI_SYSTEM)
perror("getnameinfo");
else if (error)
errx(1, "getnameinfo: %s", gai_strerror(error);
If the above getnameinfo() call is replaced with cap_getnameinfo(),
it breaks the error handling. For example, the cap_get{addr,name}info()
functions can return ENOTCAPABLE.
This change simply adds "errno", in addition to "error", to the nvlout and
cap_get{addr,name}info() restores the errno if the error code is EAI_SYSTEM.
Reviewed by: oshogbo
Differential Revision: https://reviews.freebsd.org/D45859
This commit is contained in:
@@ -288,7 +288,7 @@ cap_getaddrinfo(cap_channel_t *chan, const char *hostname, const char *servname,
|
|||||||
const nvlist_t *nvlai;
|
const nvlist_t *nvlai;
|
||||||
char nvlname[64];
|
char nvlname[64];
|
||||||
nvlist_t *nvl;
|
nvlist_t *nvl;
|
||||||
int error, n;
|
int error, serrno, n;
|
||||||
|
|
||||||
nvl = nvlist_create(0);
|
nvl = nvlist_create(0);
|
||||||
nvlist_add_string(nvl, "cmd", "getaddrinfo");
|
nvlist_add_string(nvl, "cmd", "getaddrinfo");
|
||||||
@@ -311,7 +311,9 @@ cap_getaddrinfo(cap_channel_t *chan, const char *hostname, const char *servname,
|
|||||||
return (EAI_MEMORY);
|
return (EAI_MEMORY);
|
||||||
if (nvlist_get_number(nvl, "error") != 0) {
|
if (nvlist_get_number(nvl, "error") != 0) {
|
||||||
error = (int)nvlist_get_number(nvl, "error");
|
error = (int)nvlist_get_number(nvl, "error");
|
||||||
|
serrno = dnvlist_get_number(nvl, "errno", 0);
|
||||||
nvlist_destroy(nvl);
|
nvlist_destroy(nvl);
|
||||||
|
errno = (error == EAI_SYSTEM) ? serrno : 0;
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -350,7 +352,7 @@ cap_getnameinfo(cap_channel_t *chan, const struct sockaddr *sa, socklen_t salen,
|
|||||||
char *host, size_t hostlen, char *serv, size_t servlen, int flags)
|
char *host, size_t hostlen, char *serv, size_t servlen, int flags)
|
||||||
{
|
{
|
||||||
nvlist_t *nvl;
|
nvlist_t *nvl;
|
||||||
int error;
|
int error, serrno;
|
||||||
|
|
||||||
nvl = nvlist_create(0);
|
nvl = nvlist_create(0);
|
||||||
nvlist_add_string(nvl, "cmd", "getnameinfo");
|
nvlist_add_string(nvl, "cmd", "getnameinfo");
|
||||||
@@ -363,7 +365,9 @@ cap_getnameinfo(cap_channel_t *chan, const struct sockaddr *sa, socklen_t salen,
|
|||||||
return (EAI_MEMORY);
|
return (EAI_MEMORY);
|
||||||
if (nvlist_get_number(nvl, "error") != 0) {
|
if (nvlist_get_number(nvl, "error") != 0) {
|
||||||
error = (int)nvlist_get_number(nvl, "error");
|
error = (int)nvlist_get_number(nvl, "error");
|
||||||
|
serrno = dnvlist_get_number(nvl, "errno", 0);
|
||||||
nvlist_destroy(nvl);
|
nvlist_destroy(nvl);
|
||||||
|
errno = (error == EAI_SYSTEM) ? serrno : 0;
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -858,19 +862,21 @@ net_getnameinfo(const nvlist_t *limits, const nvlist_t *nvlin, nvlist_t *nvlout)
|
|||||||
char *host, *serv;
|
char *host, *serv;
|
||||||
size_t sabinsize, hostlen, servlen;
|
size_t sabinsize, hostlen, servlen;
|
||||||
socklen_t salen;
|
socklen_t salen;
|
||||||
int error, flags;
|
int error, serrno, flags;
|
||||||
const nvlist_t *funclimit;
|
const nvlist_t *funclimit;
|
||||||
|
|
||||||
if (!net_allowed_mode(limits, CAPNET_ADDR2NAME))
|
host = serv = NULL;
|
||||||
return (ENOTCAPABLE);
|
if (!net_allowed_mode(limits, CAPNET_ADDR2NAME)) {
|
||||||
|
serrno = ENOTCAPABLE;
|
||||||
|
error = EAI_SYSTEM;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
funclimit = NULL;
|
funclimit = NULL;
|
||||||
if (limits != NULL) {
|
if (limits != NULL) {
|
||||||
funclimit = dnvlist_get_nvlist(limits, LIMIT_NV_ADDR2NAME,
|
funclimit = dnvlist_get_nvlist(limits, LIMIT_NV_ADDR2NAME,
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
error = 0;
|
error = 0;
|
||||||
host = serv = NULL;
|
|
||||||
memset(&sast, 0, sizeof(sast));
|
memset(&sast, 0, sizeof(sast));
|
||||||
|
|
||||||
hostlen = (size_t)nvlist_get_number(nvlin, "hostlen");
|
hostlen = (size_t)nvlist_get_number(nvlin, "hostlen");
|
||||||
@@ -897,7 +903,8 @@ net_getnameinfo(const nvlist_t *limits, const nvlist_t *nvlin, nvlist_t *nvlout)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
if (!net_allowed_bsaddr(funclimit, sabin, sabinsize)) {
|
if (!net_allowed_bsaddr(funclimit, sabin, sabinsize)) {
|
||||||
error = ENOTCAPABLE;
|
serrno = ENOTCAPABLE;
|
||||||
|
error = EAI_SYSTEM;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -913,7 +920,8 @@ net_getnameinfo(const nvlist_t *limits, const nvlist_t *nvlin, nvlist_t *nvlout)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!net_allowed_family(funclimit, (int)sast.ss_family)) {
|
if (!net_allowed_family(funclimit, (int)sast.ss_family)) {
|
||||||
error = ENOTCAPABLE;
|
serrno = ENOTCAPABLE;
|
||||||
|
error = EAI_SYSTEM;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -921,6 +929,7 @@ net_getnameinfo(const nvlist_t *limits, const nvlist_t *nvlin, nvlist_t *nvlout)
|
|||||||
|
|
||||||
error = getnameinfo((struct sockaddr *)&sast, salen, host, hostlen,
|
error = getnameinfo((struct sockaddr *)&sast, salen, host, hostlen,
|
||||||
serv, servlen, flags);
|
serv, servlen, flags);
|
||||||
|
serrno = errno;
|
||||||
if (error != 0)
|
if (error != 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
@@ -932,6 +941,8 @@ net_getnameinfo(const nvlist_t *limits, const nvlist_t *nvlin, nvlist_t *nvlout)
|
|||||||
if (error != 0) {
|
if (error != 0) {
|
||||||
free(host);
|
free(host);
|
||||||
free(serv);
|
free(serv);
|
||||||
|
if (error == EAI_SYSTEM)
|
||||||
|
nvlist_add_number(nvlout, "errno", serrno);
|
||||||
}
|
}
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
@@ -961,12 +972,15 @@ net_getaddrinfo(const nvlist_t *limits, const nvlist_t *nvlin, nvlist_t *nvlout)
|
|||||||
char nvlname[64];
|
char nvlname[64];
|
||||||
nvlist_t *elem;
|
nvlist_t *elem;
|
||||||
unsigned int ii;
|
unsigned int ii;
|
||||||
int error, family, n;
|
int error, serrno, family, n;
|
||||||
const nvlist_t *funclimit;
|
const nvlist_t *funclimit;
|
||||||
bool dnscache;
|
bool dnscache;
|
||||||
|
|
||||||
if (!net_allowed_mode(limits, CAPNET_NAME2ADDR))
|
if (!net_allowed_mode(limits, CAPNET_NAME2ADDR)) {
|
||||||
return (ENOTCAPABLE);
|
serrno = ENOTCAPABLE;
|
||||||
|
error = EAI_SYSTEM;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
dnscache = net_allowed_mode(limits, CAPNET_CONNECTDNS);
|
dnscache = net_allowed_mode(limits, CAPNET_CONNECTDNS);
|
||||||
funclimit = NULL;
|
funclimit = NULL;
|
||||||
if (limits != NULL) {
|
if (limits != NULL) {
|
||||||
@@ -996,11 +1010,18 @@ net_getaddrinfo(const nvlist_t *limits, const nvlist_t *nvlin, nvlist_t *nvlout)
|
|||||||
family = AF_UNSPEC;
|
family = AF_UNSPEC;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!net_allowed_family(funclimit, family))
|
if (!net_allowed_family(funclimit, family)) {
|
||||||
return (ENOTCAPABLE);
|
errno = ENOTCAPABLE;
|
||||||
if (!net_allowed_hosts(funclimit, hostname, servname))
|
error = EAI_SYSTEM;
|
||||||
return (ENOTCAPABLE);
|
goto out;
|
||||||
|
}
|
||||||
|
if (!net_allowed_hosts(funclimit, hostname, servname)) {
|
||||||
|
errno = ENOTCAPABLE;
|
||||||
|
error = EAI_SYSTEM;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
error = getaddrinfo(hostname, servname, hintsp, &res);
|
error = getaddrinfo(hostname, servname, hintsp, &res);
|
||||||
|
serrno = errno;
|
||||||
if (error != 0) {
|
if (error != 0) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@@ -1019,6 +1040,8 @@ net_getaddrinfo(const nvlist_t *limits, const nvlist_t *nvlin, nvlist_t *nvlout)
|
|||||||
freeaddrinfo(res);
|
freeaddrinfo(res);
|
||||||
error = 0;
|
error = 0;
|
||||||
out:
|
out:
|
||||||
|
if (error == EAI_SYSTEM)
|
||||||
|
nvlist_add_number(nvlout, "errno", serrno);
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user