The branch main has been updated by glebius:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=777123969db5ee8eceee28d7df72b7fd7352cb85

commit 777123969db5ee8eceee28d7df72b7fd7352cb85
Author:     Gleb Smirnoff <gleb...@freebsd.org>
AuthorDate: 2025-07-25 20:10:17 +0000
Commit:     Gleb Smirnoff <gleb...@freebsd.org>
CommitDate: 2025-07-25 20:10:17 +0000

    libbsnmp: make binding of client UNIX socket optional and configurable
    
    Before this change snmp_open(3) would always bind(2) client socket to a
    random "/tmp/snmpXXXXXXXXXXXXXX" name.  However, this binding is not
    required for SOCK_STREAM transport.  Also, any attempt to specify a
    different name would fail, as open_client_local() would blindly rewrite
    the name to the default.
    
    Make this binding optional.  If application had initialized
    snmp_client.local_path, then try to bind to the specified pathname,
    otherwise perform the random name binding only if we are in the
    SOCK_DGRAM mode.
    
    While here change snmp_client.local_path size to SUNPATHLEN, so that any
    legitimate local socket name can be used.  This requires library version
    bump.
    
    Note that this code has been broken by 81e0e7b9e36d for three years, thus
    it is known not to be widely used.
    
    Reviewed by:            harti
    Differential Revision:  https://reviews.freebsd.org/D51070
---
 ObsoleteFiles.inc                                |  3 +
 contrib/bsnmp/lib/bsnmpclient.3                  | 19 ++++--
 contrib/bsnmp/lib/snmpclient.c                   | 74 ++++++++++++++----------
 contrib/bsnmp/lib/snmpclient.h                   |  5 +-
 lib/libbsnmp/libbsnmp/Makefile                   |  2 +-
 tools/build/mk/OptionalObsoleteFiles.inc         |  2 +-
 usr.sbin/bsnmpd/tools/libbsnmptools/bsnmptools.c |  5 +-
 7 files changed, 69 insertions(+), 41 deletions(-)

diff --git a/ObsoleteFiles.inc b/ObsoleteFiles.inc
index 808e7be828c5..385e891049e7 100644
--- a/ObsoleteFiles.inc
+++ b/ObsoleteFiles.inc
@@ -51,6 +51,9 @@
 #   xargs -n1 | sort | uniq -d;
 # done
 
+# 20250725: libbsnmp bumped to version 7
+OLD_LIBS+=usr/lib/libbsnmp.so.6
+
 # 20250725: Files which were briefly installed by WITH_MITKRB5 in 15.0.
 OLD_FILES+=usr/include/kadm5/admin_internal.h
 OLD_FILES+=usr/include/kadm5/admin_xdr.h
diff --git a/contrib/bsnmp/lib/bsnmpclient.3 b/contrib/bsnmp/lib/bsnmpclient.3
index 0a2286eb14c4..1a5aa2e5e3a6 100644
--- a/contrib/bsnmp/lib/bsnmpclient.3
+++ b/contrib/bsnmp/lib/bsnmpclient.3
@@ -31,7 +31,7 @@
 .\"
 .\" $Begemot: bsnmp/lib/bsnmpclient.3,v 1.12 2005/10/04 08:46:50 brandt_h Exp $
 .\"
-.Dd March 31, 2020
+.Dd June 24, 2025
 .Dt BSNMPCLIENT 3
 .Os
 .Sh NAME
@@ -155,7 +155,7 @@ struct snmp_client {
        snmp_timeout_start_f    timeout_start;
        snmp_timeout_stop_f     timeout_stop;
 
-       char                    local_path[sizeof(SNMP_LOCAL_PATH)];
+       char                    local_path[SUNPATHLEN];
 };
 .Ed
 .Pp
@@ -285,8 +285,19 @@ The function will be called with the return value of the 
corresponding
 .Fn timeout_start
 function.
 .It Va local_path
-If in local socket mode, the name of the clients socket.
-Not needed by the application.
+In local socket mode, optional path name the client socket shall be bound to
+before connecting to the server.
+For
+.Dv SOCK_STREAM
+local socket the named path is optional, and library will skip
+.Xr bind 2
+if path is not provided.
+For
+.Dv SOCK_DGRAM
+local socket the named path is required, thus library will create a random
+one in
+.Pa /tmp
+if path is not provided.
 .El
 .Pp
 In the current implementation there is a global variable
diff --git a/contrib/bsnmp/lib/snmpclient.c b/contrib/bsnmp/lib/snmpclient.c
index d5d4af998a0c..5fa7d4f5be2a 100644
--- a/contrib/bsnmp/lib/snmpclient.c
+++ b/contrib/bsnmp/lib/snmpclient.c
@@ -977,7 +977,10 @@ remove_local(void)
 static int
 open_client_local(const char *path)
 {
-       struct sockaddr_un sa;
+       struct sockaddr_un sa = {
+               .sun_family = AF_LOCAL,
+               .sun_len = sizeof(sa),
+       };
        char *ptr;
        int stype;
 
@@ -1003,43 +1006,56 @@ open_client_local(const char *path)
                return (-1);
        }
 
-       snprintf(snmp_client.local_path, sizeof(snmp_client.local_path),
-           "%s", SNMP_LOCAL_PATH);
-
-       if (mktemp(snmp_client.local_path) == NULL) {
-               seterr(&snmp_client, "%s", strerror(errno));
-               (void)close(snmp_client.fd);
-               snmp_client.fd = -1;
-               return (-1);
+       /*
+        * A datagram socket requires a name to receive replies back.  Would
+        * be cool to have an extension to unix(4) sockets similar to ip(4)
+        * IP_RECVDSTADDR/IP_SENDSRCADDR, so that a one-to-many datagram
+        * UNIX socket can send replies to its anonymous peers.
+        */
+       if (snmp_client.trans == SNMP_TRANS_LOC_DGRAM &&
+           snmp_client.local_path[0] == '\0') {
+               (void)strlcpy(snmp_client.local_path, "/tmp/snmpXXXXXXXXXXXXXX",
+                   sizeof(snmp_client.local_path));
+               if (mktemp(snmp_client.local_path) == NULL) {
+                       seterr(&snmp_client, "mktemp(3): %s", strerror(errno));
+                       goto fail;
+               }
        }
 
-       sa.sun_family = AF_LOCAL;
-       sa.sun_len = sizeof(sa);
-       strcpy(sa.sun_path, snmp_client.local_path);
-
-       if (bind(snmp_client.fd, (struct sockaddr *)&sa, sizeof(sa)) == -1) {
-               seterr(&snmp_client, "%s", strerror(errno));
-               (void)close(snmp_client.fd);
-               snmp_client.fd = -1;
-               (void)remove(snmp_client.local_path);
-               return (-1);
+       if (snmp_client.local_path[0] != '\0') {
+               if (strlcpy(sa.sun_path, snmp_client.local_path,
+                   sizeof(sa.sun_path)) >=
+                   sizeof(sa.sun_path)) {
+                       seterr(&snmp_client, "%s",
+                           "Local socket pathname too long");
+                       goto fail;
+               }
+               if (bind(snmp_client.fd, (struct sockaddr *)&sa, sizeof(sa)) ==
+                   -1) {
+                       seterr(&snmp_client, "%s", strerror(errno));
+                       goto fail;
+               }
+               atexit(remove_local);
        }
-       atexit(remove_local);
 
-       sa.sun_family = AF_LOCAL;
-       sa.sun_len = offsetof(struct sockaddr_un, sun_path) +
-           strlen(snmp_client.chost);
-       strncpy(sa.sun_path, snmp_client.chost, sizeof(sa.sun_path) - 1);
-       sa.sun_path[sizeof(sa.sun_path) - 1] = '\0';
+       if (strlcpy(sa.sun_path, snmp_client.chost, sizeof(sa.sun_path)) >=
+           sizeof(sa.sun_path)) {
+               seterr(&snmp_client, "%s", "Server socket pathname too long");
+               goto fail;
+       }
 
        if (connect(snmp_client.fd, (struct sockaddr *)&sa, sa.sun_len) == -1) {
                seterr(&snmp_client, "%s", strerror(errno));
-               (void)close(snmp_client.fd);
-               snmp_client.fd = -1;
-               (void)remove(snmp_client.local_path);
-               return (-1);
+               goto fail;
        }
        return (0);
+
+fail:
+       (void)close(snmp_client.fd);
+       snmp_client.fd = -1;
+       if (snmp_client.local_path[0] != '\0')
+               (void)remove(snmp_client.local_path);
+       return (-1);
 }
 
 /*
diff --git a/contrib/bsnmp/lib/snmpclient.h b/contrib/bsnmp/lib/snmpclient.h
index 662dc7c4a204..a8a79ff824bc 100644
--- a/contrib/bsnmp/lib/snmpclient.h
+++ b/contrib/bsnmp/lib/snmpclient.h
@@ -35,6 +35,7 @@
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/time.h>
+#include <sys/un.h>
 #include <netinet/in.h>
 #include <stddef.h>
 
@@ -42,8 +43,6 @@
 #define SNMP_STRERROR_LEN 200
 #define        SNMP_DEFAULT_LOCAL "/var/run/snmpd.sock"
 
-#define SNMP_LOCAL_PATH        "/tmp/snmpXXXXXXXXXXXXXX"
-
 /*
  * transport methods
  */
@@ -111,7 +110,7 @@ struct snmp_client {
        snmp_timeout_start_f    timeout_start;
        snmp_timeout_stop_f     timeout_stop;
 
-       char                    local_path[sizeof(SNMP_LOCAL_PATH)];
+       char                    local_path[SUNPATHLEN];
 };
 
 /* the global context */
diff --git a/lib/libbsnmp/libbsnmp/Makefile b/lib/libbsnmp/libbsnmp/Makefile
index 6bdb4003fdf4..2e2770b56c4a 100644
--- a/lib/libbsnmp/libbsnmp/Makefile
+++ b/lib/libbsnmp/libbsnmp/Makefile
@@ -7,7 +7,7 @@ CONTRIB= ${SRCTOP}/contrib/bsnmp/lib
 .PATH: ${CONTRIB}
 
 LIB=   bsnmp
-SHLIB_MAJOR=   6
+SHLIB_MAJOR=   7
 LD_FATAL_WARNINGS=     no
 
 CFLAGS+= -I${CONTRIB} -DHAVE_ERR_H -DHAVE_GETADDRINFO -DHAVE_STRLCPY
diff --git a/tools/build/mk/OptionalObsoleteFiles.inc 
b/tools/build/mk/OptionalObsoleteFiles.inc
index 4c127b392138..3183c5f0b45c 100644
--- a/tools/build/mk/OptionalObsoleteFiles.inc
+++ b/tools/build/mk/OptionalObsoleteFiles.inc
@@ -461,7 +461,7 @@ OLD_FILES+=usr/include/bsnmp/snmpclient.h
 OLD_FILES+=usr/include/bsnmp/snmpmod.h
 OLD_FILES+=usr/lib/libbsnmp.a
 OLD_FILES+=usr/lib/libbsnmp.so
-OLD_LIBS+=usr/lib/libbsnmp.so.6
+OLD_LIBS+=usr/lib/libbsnmp.so.7
 OLD_FILES+=usr/lib/libbsnmp_p.a
 OLD_FILES+=usr/lib/libbsnmptools.a
 OLD_FILES+=usr/lib/libbsnmptools.so
diff --git a/usr.sbin/bsnmpd/tools/libbsnmptools/bsnmptools.c 
b/usr.sbin/bsnmpd/tools/libbsnmptools/bsnmptools.c
index b4613763fff5..d8fbb55290a8 100644
--- a/usr.sbin/bsnmpd/tools/libbsnmptools/bsnmptools.c
+++ b/usr.sbin/bsnmpd/tools/libbsnmptools/bsnmptools.c
@@ -881,12 +881,11 @@ parse_local_path(char *opt_arg)
 {
        assert(opt_arg != NULL);
 
-       if (sizeof(opt_arg) > sizeof(SNMP_LOCAL_PATH)) {
+       if (strlcpy(snmp_client.local_path, opt_arg,
+           sizeof(snmp_client.local_path)) >= sizeof(snmp_client.local_path)) {
                warnx("Filename too long - %s", opt_arg);
                return (-1);
        }
-
-       strlcpy(snmp_client.local_path, opt_arg, sizeof(SNMP_LOCAL_PATH));
        return (2);
 }
 

Reply via email to