This may be useful for testing and on some networks where both address
families are available but only one works or is desired. The last option
specified takes precedence. If neither option is specified, the usual
behaviour (AF_UNSPEC) remains.
---
bounce.c | 9 +++++++--
bounce.h | 2 +-
pounce.1 | 6 +++++-
server.c | 4 ++--
4 files changed, 15 insertions(+), 6 deletions(-)
diff --git a/bounce.c b/bounce.c
index e9fcd0b..bcc9b36 100644
--- a/bounce.c
+++ b/bounce.c
@@ -158,6 +158,7 @@ int main(int argc, char *argv[]) {
const char *clientPriv = NULL;
const char *serverBindHost = NULL;
+ int ai_family = 0;
const char *host = NULL;
const char *port = "6697";
char *pass = NULL;
@@ -173,6 +174,8 @@ int main(int argc, char *argv[]) {
struct option options[] = {
{ .val = '!', .name = "insecure", no_argument },
+ { .val = '4', .name = "ipv4", no_argument },
+ { .val = '6', .name = "ipv6", no_argument },
{ .val = 'A', .name = "local-ca", required_argument },
{ .val = 'C', .name = "local-cert", required_argument },
{ .val = 'H', .name = "local-host", required_argument },
@@ -218,6 +221,8 @@ int main(int argc, char *argv[]) {
for (int opt; 0 < (opt = getopt_config(argc, argv, opts, options, NULL));) {
switch (opt) {
break; case '!': insecure = true;
+ break; case '4': ai_family = 4;
+ break; case '6': ai_family = 6;
break; case 'A': caPath = optarg; clientCaps |= CapSASL;
break; case 'C': snprintf(certPath, sizeof(certPath), "%s", optarg);
break; case 'H': bindHost = optarg;
@@ -292,7 +297,7 @@ int main(int argc, char *argv[]) {
if (error) err(EX_OSERR, "pledge");
#endif
serverConfig(true, NULL, NULL, NULL);
- serverConnect(serverBindHost, host, port);
+ serverConnect(serverBindHost, host, port, ai_family);
serverPrintCert();
serverClose();
return EX_OK;
@@ -338,7 +343,7 @@ int main(int argc, char *argv[]) {
size_t binds = bindPath[0]
? localUnix(bind, ARRAY_LEN(bind), bindPath)
: localBind(bind, ARRAY_LEN(bind), bindHost, bindPort);
- int server = serverConnect(serverBindHost, host, port);
+ int server = serverConnect(serverBindHost, host, port, ai_family);
#ifdef __OpenBSD__
if (bindPath[0]) {
diff --git a/bounce.h b/bounce.h
index 8e6ed09..f3ab615 100644
--- a/bounce.h
+++ b/bounce.h
@@ -194,7 +194,7 @@ extern struct timeval serverQueueInterval;
void serverConfig(
bool insecure, const char *trust, const char *cert, const char *priv
);
-int serverConnect(const char *bindHost, const char *host, const char *port);
+int serverConnect(const char *bindHost, const char *host, const char *port, int ai_family);
void serverPrintCert(void);
void serverRecv(void);
void serverSend(const char *ptr, size_t len);
diff --git a/pounce.1 b/pounce.1
index 4c4c517..36a0b41 100644
--- a/pounce.1
+++ b/pounce.1
@@ -8,7 +8,7 @@
.
.Sh SYNOPSIS
.Nm
-.Op Fl LNTev
+.Op Fl 46LNTev
.Op Fl A Ar local-ca
.Op Fl C Ar local-cert
.Op Fl H Ar local-host
@@ -265,6 +265,10 @@ The default size is 4096.
.
.Ss Remote Server Options
.Bl -tag -width Ds
+.It Fl 4 | Cm ipv4
+Use IPv4 only.
+.It Fl 6 | Cm ipv6
+Use IPv6 only.
.It Fl N | Cm no-names
Do not request
.Ql NAMES
diff --git a/server.c b/server.c
index 0c6bccc..2031c64 100644
--- a/server.c
+++ b/server.c
@@ -92,14 +92,14 @@ void serverConfig(
if (error) errx(EX_SOFTWARE, "tls_configure: %s", tls_error(client));
}
-int serverConnect(const char *bindHost, const char *host, const char *port) {
+int serverConnect(const char *bindHost, const char *host, const char *port, int ai_family) {
assert(client);
int error;
int sock = -1;
struct addrinfo *head;
struct addrinfo hints = {
- .ai_family = AF_UNSPEC,
+ .ai_family = ai_family == 4 ? AF_INET : ai_family == 6 ? AF_INET6 : AF_UNSPEC,
.ai_socktype = SOCK_STREAM,
.ai_protocol = IPPROTO_TCP,
};
--
2.34.1