git: b60053fde172 - main - libcasper: Fix inconsistent error codes of cap_get{addr,name}info()
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 12 Jun 2025 18:17:25 UTC
The branch main has been updated by hrs:
URL: https://cgit.FreeBSD.org/src/commit/?id=b60053fde1726ea047aadfbc0354b79e99d4a668
commit b60053fde1726ea047aadfbc0354b79e99d4a668
Author: Hiroki Sato <hrs@FreeBSD.org>
AuthorDate: 2025-06-12 18:16:18 +0000
Commit: Hiroki Sato <hrs@FreeBSD.org>
CommitDate: 2025-06-12 18:16:49 +0000
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
---
lib/libcasper/services/cap_net/cap_net.c | 55 ++++++++++++++++++++++----------
1 file changed, 39 insertions(+), 16 deletions(-)
diff --git a/lib/libcasper/services/cap_net/cap_net.c b/lib/libcasper/services/cap_net/cap_net.c
index 40d18319ae28..5887fe3c407e 100644
--- a/lib/libcasper/services/cap_net/cap_net.c
+++ b/lib/libcasper/services/cap_net/cap_net.c
@@ -288,7 +288,7 @@ cap_getaddrinfo(cap_channel_t *chan, const char *hostname, const char *servname,
const nvlist_t *nvlai;
char nvlname[64];
nvlist_t *nvl;
- int error, n;
+ int error, serrno, n;
nvl = nvlist_create(0);
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);
if (nvlist_get_number(nvl, "error") != 0) {
error = (int)nvlist_get_number(nvl, "error");
+ serrno = dnvlist_get_number(nvl, "errno", 0);
nvlist_destroy(nvl);
+ errno = (error == EAI_SYSTEM) ? serrno : 0;
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)
{
nvlist_t *nvl;
- int error;
+ int error, serrno;
nvl = nvlist_create(0);
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);
if (nvlist_get_number(nvl, "error") != 0) {
error = (int)nvlist_get_number(nvl, "error");
+ serrno = dnvlist_get_number(nvl, "errno", 0);
nvlist_destroy(nvl);
+ errno = (error == EAI_SYSTEM) ? serrno : 0;
return (error);
}
@@ -858,19 +862,21 @@ net_getnameinfo(const nvlist_t *limits, const nvlist_t *nvlin, nvlist_t *nvlout)
char *host, *serv;
size_t sabinsize, hostlen, servlen;
socklen_t salen;
- int error, flags;
+ int error, serrno, flags;
const nvlist_t *funclimit;
- if (!net_allowed_mode(limits, CAPNET_ADDR2NAME))
- return (ENOTCAPABLE);
+ host = serv = NULL;
+ if (!net_allowed_mode(limits, CAPNET_ADDR2NAME)) {
+ serrno = ENOTCAPABLE;
+ error = EAI_SYSTEM;
+ goto out;
+ }
funclimit = NULL;
if (limits != NULL) {
funclimit = dnvlist_get_nvlist(limits, LIMIT_NV_ADDR2NAME,
NULL);
}
-
error = 0;
- host = serv = NULL;
memset(&sast, 0, sizeof(sast));
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;
}
if (!net_allowed_bsaddr(funclimit, sabin, sabinsize)) {
- error = ENOTCAPABLE;
+ serrno = ENOTCAPABLE;
+ error = EAI_SYSTEM;
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)) {
- error = ENOTCAPABLE;
+ serrno = ENOTCAPABLE;
+ error = EAI_SYSTEM;
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,
serv, servlen, flags);
+ serrno = errno;
if (error != 0)
goto out;
@@ -932,6 +941,8 @@ out:
if (error != 0) {
free(host);
free(serv);
+ if (error == EAI_SYSTEM)
+ nvlist_add_number(nvlout, "errno", serrno);
}
return (error);
}
@@ -961,12 +972,15 @@ net_getaddrinfo(const nvlist_t *limits, const nvlist_t *nvlin, nvlist_t *nvlout)
char nvlname[64];
nvlist_t *elem;
unsigned int ii;
- int error, family, n;
+ int error, serrno, family, n;
const nvlist_t *funclimit;
bool dnscache;
- if (!net_allowed_mode(limits, CAPNET_NAME2ADDR))
- return (ENOTCAPABLE);
+ if (!net_allowed_mode(limits, CAPNET_NAME2ADDR)) {
+ serrno = ENOTCAPABLE;
+ error = EAI_SYSTEM;
+ goto out;
+ }
dnscache = net_allowed_mode(limits, CAPNET_CONNECTDNS);
funclimit = NULL;
if (limits != NULL) {
@@ -996,11 +1010,18 @@ net_getaddrinfo(const nvlist_t *limits, const nvlist_t *nvlin, nvlist_t *nvlout)
family = AF_UNSPEC;
}
- if (!net_allowed_family(funclimit, family))
- return (ENOTCAPABLE);
- if (!net_allowed_hosts(funclimit, hostname, servname))
- return (ENOTCAPABLE);
+ if (!net_allowed_family(funclimit, family)) {
+ errno = ENOTCAPABLE;
+ error = EAI_SYSTEM;
+ goto out;
+ }
+ if (!net_allowed_hosts(funclimit, hostname, servname)) {
+ errno = ENOTCAPABLE;
+ error = EAI_SYSTEM;
+ goto out;
+ }
error = getaddrinfo(hostname, servname, hintsp, &res);
+ serrno = errno;
if (error != 0) {
goto out;
}
@@ -1019,6 +1040,8 @@ net_getaddrinfo(const nvlist_t *limits, const nvlist_t *nvlin, nvlist_t *nvlout)
freeaddrinfo(res);
error = 0;
out:
+ if (error == EAI_SYSTEM)
+ nvlist_add_number(nvlout, "errno", serrno);
return (error);
}