Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 12 Jun 2025 18:17:25 GMT
From:      Hiroki Sato <hrs@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: b60053fde172 - main - libcasper: Fix inconsistent error codes of cap_get{addr,name}info()
Message-ID:  <202506121817.55CIHPIB087707@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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);
 }
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202506121817.55CIHPIB087707>