aboutsummaryrefslogtreecommitdiff
path: root/contrib
diff options
context:
space:
mode:
authorGleb Smirnoff <glebius@FreeBSD.org>2025-07-25 20:10:17 +0000
committerGleb Smirnoff <glebius@FreeBSD.org>2025-07-25 20:10:17 +0000
commit777123969db5ee8eceee28d7df72b7fd7352cb85 (patch)
tree724d93bd5a3bdfa68484c8f54a742e0266afbc0d /contrib
parentb9fa99600a78c66dce9040595f04bfe2ba25652c (diff)
Diffstat (limited to 'contrib')
-rw-r--r--contrib/bsnmp/lib/bsnmpclient.319
-rw-r--r--contrib/bsnmp/lib/snmpclient.c74
-rw-r--r--contrib/bsnmp/lib/snmpclient.h5
3 files changed, 62 insertions, 36 deletions
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 */