Works essentially just like calling getpeername(2), because that's how
it is implemented.
---
TODO | 6 ++++++
docs/nbdkit-plugin.pod | 23 +++++++++++++++++++++++
include/nbdkit-common.h | 2 ++
server/nbdkit.syms | 1 +
server/public.c | 21 +++++++++++++++++++++
5 files changed, 53 insertions(+)
diff --git a/TODO b/TODO
index 04def3c..d2cf0ae 100644
--- a/TODO
+++ b/TODO
@@ -77,6 +77,12 @@ General ideas for improvements
name(s) that a plugin might want to support. Probably we should
deprecate the -e option entirely since it does nothing useful.
+* Add plugin "connect" method. This would be called on a connection
+ before handshaking or TLS negotiation, and could be used (with
+ nbdkit_peer_name) to accept or reject connections based on IP
+ address, rather like a poor man's TCP wrappers. See also commit
+ c05686f9577f.
+
Suggestions for plugins
-----------------------
diff --git a/docs/nbdkit-plugin.pod b/docs/nbdkit-plugin.pod
index 39fa643..70d2d64 100644
--- a/docs/nbdkit-plugin.pod
+++ b/docs/nbdkit-plugin.pod
@@ -391,6 +391,29 @@ On error, C<nbdkit_error> is called and the call returns
C<NULL>.
See also L<nbdkit-reflection-plugin(1)>.
+=head1 PEER NAME
+
+It is possible to get the address of the client when you are running
+in any connected callback.
+
+=head2 C<nbdkit_peer_name>
+
+ int nbdkit_peer_name (struct sockaddr *addr, socklen_t *addrlen);
+
+Return the peer (client) address, if available. The C<addr> and
+C<addrlen> parameters behave like L<getpeername(2)>. In particular
+you must initialize C<addrlen> with the size of the buffer pointed to
+by C<addr>, and if C<addr> is not large enough then the address will
+be truncated.
+
+In some cases this is not available or the address returned will be
+meaningless (eg. if there is a proxy between the client and nbdkit).
+This call uses thread-local magic so no parameter is required to
+specify the current connection.
+
+On success this returns C<0>. On error, C<nbdkit_error> is called and
+this call returns C<-1>.
+
=head1 CALLBACKS
=head2 C<.name>
diff --git a/include/nbdkit-common.h b/include/nbdkit-common.h
index acf0abd..aac63fb 100644
--- a/include/nbdkit-common.h
+++ b/include/nbdkit-common.h
@@ -40,6 +40,7 @@
#include <stdarg.h>
#include <stdint.h>
#include <errno.h>
+#include <sys/socket.h>
#include <nbdkit-version.h>
@@ -87,6 +88,7 @@ extern int nbdkit_read_password (const char *value, char **password);
extern char *nbdkit_realpath (const char *path);
extern int nbdkit_nanosleep (unsigned sec, unsigned nsec);
extern const char *nbdkit_export_name (void);
+extern int nbdkit_peer_name (struct sockaddr *addr, socklen_t *addrlen);
struct nbdkit_extents;
extern int nbdkit_add_extent (struct nbdkit_extents *,
diff --git a/server/nbdkit.syms b/server/nbdkit.syms
index 1fb1315..d792a5f 100644
--- a/server/nbdkit.syms
+++ b/server/nbdkit.syms
@@ -50,6 +50,7 @@
nbdkit_nanosleep;
nbdkit_parse_bool;
nbdkit_parse_size;
+ nbdkit_peer_name;
nbdkit_read_password;
nbdkit_realpath;
nbdkit_set_error;
diff --git a/server/public.c b/server/public.c
index 96ab353..c8b06a6 100644
--- a/server/public.c
+++ b/server/public.c
@@ -49,6 +49,7 @@
#include <errno.h>
#include <poll.h>
#include <signal.h>
+#include <sys/socket.h>
#include "get-current-dir-name.h"
@@ -392,3 +393,23 @@ nbdkit_export_name (void)
return conn->exportname;
}
+
+int
+nbdkit_peer_name (struct sockaddr *addr, socklen_t *addrlen)
+{
+ struct connection *conn = threadlocal_get_conn ();
+ int s;
+
+ if (!conn) {
+ nbdkit_error ("no connection in this thread");
+ return -1;
+ }
+
+ s = conn->sockin;
+ if (s == -1) {
+ nbdkit_error ("socket not open");
+ return -1;
+ }
+
+ return getpeername (s, addr, addrlen);
+}
--
2.23.0