summaryrefslogtreecommitdiff
path: root/testcode/streamtcp.c
diff options
context:
space:
mode:
authorCy Schubert <cy@FreeBSD.org>2022-10-16 19:24:20 +0000
committerCy Schubert <cy@FreeBSD.org>2022-10-16 19:24:20 +0000
commit643f9a0581e8aac7eb790ced1164748939829826 (patch)
tree426d366252d838c8c61b439342ab32eccd181425 /testcode/streamtcp.c
parent0dde6f4f8e604df8c6fbdab8b4aadb5ddf80c76f (diff)
Diffstat (limited to 'testcode/streamtcp.c')
-rw-r--r--testcode/streamtcp.c128
1 files changed, 101 insertions, 27 deletions
diff --git a/testcode/streamtcp.c b/testcode/streamtcp.c
index ecc83c1cff30..b2c0d5328bb7 100644
--- a/testcode/streamtcp.c
+++ b/testcode/streamtcp.c
@@ -49,6 +49,7 @@
#include "util/locks.h"
#include "util/log.h"
#include "util/net_help.h"
+#include "util/proxy_protocol.h"
#include "util/data/msgencode.h"
#include "util/data/msgparse.h"
#include "util/data/msgreply.h"
@@ -71,6 +72,7 @@ static void usage(char* argv[])
printf("usage: %s [options] name type class ...\n", argv[0]);
printf(" sends the name-type-class queries over TCP.\n");
printf("-f server what ipaddr@portnr to send the queries to\n");
+ printf("-p client what ipaddr@portnr to include in PROXYv2\n");
printf("-u use UDP. No retries are attempted.\n");
printf("-n do not wait for an answer.\n");
printf("-a print answers as they arrive.\n");
@@ -82,18 +84,17 @@ static void usage(char* argv[])
/** open TCP socket to svr */
static int
-open_svr(const char* svr, int udp)
+open_svr(const char* svr, int udp, struct sockaddr_storage* addr,
+ socklen_t* addrlen)
{
- struct sockaddr_storage addr;
- socklen_t addrlen;
int fd = -1;
/* svr can be ip@port */
- memset(&addr, 0, sizeof(addr));
- if(!extstrtoaddr(svr, &addr, &addrlen)) {
+ memset(addr, 0, sizeof(*addr));
+ if(!extstrtoaddr(svr, addr, addrlen, UNBOUND_DNS_PORT)) {
printf("fatal: bad server specs '%s'\n", svr);
exit(1);
}
- fd = socket(addr_is_ip6(&addr, addrlen)?PF_INET6:PF_INET,
+ fd = socket(addr_is_ip6(addr, *addrlen)?PF_INET6:PF_INET,
udp?SOCK_DGRAM:SOCK_STREAM, 0);
if(fd == -1) {
#ifndef USE_WINSOCK
@@ -103,7 +104,7 @@ open_svr(const char* svr, int udp)
#endif
exit(1);
}
- if(connect(fd, (struct sockaddr*)&addr, addrlen) < 0) {
+ if(connect(fd, (struct sockaddr*)addr, *addrlen) < 0) {
#ifndef USE_WINSOCK
perror("connect() error");
#else
@@ -116,11 +117,12 @@ open_svr(const char* svr, int udp)
/** write a query over the TCP fd */
static void
-write_q(int fd, int udp, SSL* ssl, sldns_buffer* buf, uint16_t id,
+write_q(int fd, int udp, SSL* ssl, sldns_buffer* buf, uint16_t id,
+ sldns_buffer* proxy_buf, int pp2_parsed,
const char* strname, const char* strtype, const char* strclass)
{
struct query_info qinfo;
- uint16_t len;
+ size_t proxy_buf_limit = sldns_buffer_limit(proxy_buf);
/* qname */
qinfo.qname = sldns_str2wire_dname(strname, &qinfo.qname_len);
if(!qinfo.qname) {
@@ -152,9 +154,27 @@ write_q(int fd, int udp, SSL* ssl, sldns_buffer* buf, uint16_t id,
attach_edns_record(buf, &edns);
}
+ /* we need to send the PROXYv2 information in every UDP message */
+ if(udp && pp2_parsed) {
+ /* append the proxy_buf with the buf's content
+ * and use that for sending */
+ if(sldns_buffer_capacity(proxy_buf) <
+ sldns_buffer_limit(proxy_buf) +
+ sldns_buffer_limit(buf)) {
+ printf("buffer too small for packet + proxy");
+ exit(1);
+ }
+ sldns_buffer_clear(proxy_buf);
+ sldns_buffer_skip(proxy_buf, proxy_buf_limit);
+ sldns_buffer_write(proxy_buf, sldns_buffer_begin(buf),
+ sldns_buffer_limit(buf));
+ sldns_buffer_flip(proxy_buf);
+ buf = proxy_buf;
+ }
+
/* send it */
if(!udp) {
- len = (uint16_t)sldns_buffer_limit(buf);
+ uint16_t len = (uint16_t)sldns_buffer_limit(buf);
len = htons(len);
if(ssl) {
if(SSL_write(ssl, (void*)&len, (int)sizeof(len)) <= 0) {
@@ -167,7 +187,7 @@ write_q(int fd, int udp, SSL* ssl, sldns_buffer* buf, uint16_t id,
#ifndef USE_WINSOCK
perror("send() len failed");
#else
- printf("send len: %s\n",
+ printf("send len: %s\n",
wsa_strerror(WSAGetLastError()));
#endif
exit(1);
@@ -182,17 +202,20 @@ write_q(int fd, int udp, SSL* ssl, sldns_buffer* buf, uint16_t id,
}
} else {
if(send(fd, (void*)sldns_buffer_begin(buf),
- sldns_buffer_limit(buf), 0) <
+ sldns_buffer_limit(buf), 0) <
(ssize_t)sldns_buffer_limit(buf)) {
#ifndef USE_WINSOCK
perror("send() data failed");
#else
- printf("send data: %s\n", wsa_strerror(WSAGetLastError()));
+ printf("send data: %s\n",
+ wsa_strerror(WSAGetLastError()));
#endif
exit(1);
}
}
+ /* reset the proxy_buf for next packet */
+ sldns_buffer_set_limit(proxy_buf, proxy_buf_limit);
free(qinfo.qname);
}
@@ -224,7 +247,7 @@ recv_one(int fd, int udp, SSL* ssl, sldns_buffer* buf)
#ifndef USE_WINSOCK
perror("read() len failed");
#else
- printf("read len: %s\n",
+ printf("read len: %s\n",
wsa_strerror(WSAGetLastError()));
#endif
exit(1);
@@ -243,12 +266,12 @@ recv_one(int fd, int udp, SSL* ssl, sldns_buffer* buf)
if(r != (int)len)
fatal_exit("ssl_read %d of %d", r, len);
} else {
- if(recv(fd, (void*)sldns_buffer_begin(buf), len, 0) <
+ if(recv(fd, (void*)sldns_buffer_begin(buf), len, 0) <
(ssize_t)len) {
#ifndef USE_WINSOCK
perror("read() data failed");
#else
- printf("read data: %s\n",
+ printf("read data: %s\n",
wsa_strerror(WSAGetLastError()));
#endif
exit(1);
@@ -257,12 +280,12 @@ recv_one(int fd, int udp, SSL* ssl, sldns_buffer* buf)
} else {
ssize_t l;
sldns_buffer_clear(buf);
- if((l=recv(fd, (void*)sldns_buffer_begin(buf),
+ if((l=recv(fd, (void*)sldns_buffer_begin(buf),
sldns_buffer_capacity(buf), 0)) < 0) {
#ifndef USE_WINSOCK
perror("read() data failed");
#else
- printf("read data: %s\n",
+ printf("read data: %s\n",
wsa_strerror(WSAGetLastError()));
#endif
exit(1);
@@ -324,17 +347,40 @@ static int get_random(void)
return (int)arc4random();
}
+/* parse the pp2_client and populate the proxy_buffer
+ * It doesn't populate the destination parts. */
+static int parse_pp2_client(const char* pp2_client, int udp,
+ sldns_buffer* proxy_buf)
+{
+ struct sockaddr_storage pp2_addr;
+ socklen_t pp2_addrlen = 0;
+ memset(&pp2_addr, 0, sizeof(pp2_addr));
+ if(*pp2_client == 0) return 0;
+ if(!extstrtoaddr(pp2_client, &pp2_addr, &pp2_addrlen, UNBOUND_DNS_PORT)) {
+ printf("fatal: bad proxy client specs '%s'\n", pp2_client);
+ exit(1);
+ }
+ sldns_buffer_clear(proxy_buf);
+ pp2_write_to_buf(proxy_buf, &pp2_addr, !udp);
+ sldns_buffer_flip(proxy_buf);
+ return 1;
+}
+
/** send the TCP queries and print answers */
static void
-send_em(const char* svr, int udp, int usessl, int noanswer, int onarrival,
- int delay, int num, char** qs)
+send_em(const char* svr, const char* pp2_client, int udp, int usessl,
+ int noanswer, int onarrival, int delay, int num, char** qs)
{
sldns_buffer* buf = sldns_buffer_new(65553);
- int fd = open_svr(svr, udp);
- int i, wait_results = 0;
+ sldns_buffer* proxy_buf = sldns_buffer_new(65553);
+ struct sockaddr_storage svr_addr;
+ socklen_t svr_addrlen;
+ int fd = open_svr(svr, udp, &svr_addr, &svr_addrlen);
+ int i, wait_results = 0, pp2_parsed;
SSL_CTX* ctx = NULL;
SSL* ssl = NULL;
if(!buf) fatal_exit("out of memory");
+ pp2_parsed = parse_pp2_client(pp2_client, udp, proxy_buf);
if(usessl) {
ctx = connect_sslctx_create(NULL, NULL, NULL, 0);
if(!ctx) fatal_exit("cannot create ssl ctx");
@@ -361,6 +407,28 @@ send_em(const char* svr, int udp, int usessl, int noanswer, int onarrival,
}
}
}
+ /* Send the PROXYv2 information once per stream */
+ if(!udp && pp2_parsed) {
+ if(ssl) {
+ if(SSL_write(ssl, (void*)sldns_buffer_begin(proxy_buf),
+ (int)sldns_buffer_limit(proxy_buf)) <= 0) {
+ log_crypto_err("cannot SSL_write");
+ exit(1);
+ }
+ } else {
+ if(send(fd, (void*)sldns_buffer_begin(proxy_buf),
+ sldns_buffer_limit(proxy_buf), 0) <
+ (ssize_t)sldns_buffer_limit(proxy_buf)) {
+#ifndef USE_WINSOCK
+ perror("send() data failed");
+#else
+ printf("send data: %s\n",
+ wsa_strerror(WSAGetLastError()));
+#endif
+ exit(1);
+ }
+ }
+ }
for(i=0; i<num; i+=3) {
if (delay != 0) {
#ifdef HAVE_SLEEP
@@ -370,8 +438,9 @@ send_em(const char* svr, int udp, int usessl, int noanswer, int onarrival,
#endif
}
printf("\nNext query is %s %s %s\n", qs[i], qs[i+1], qs[i+2]);
- write_q(fd, udp, ssl, buf, (uint16_t)get_random(), qs[i],
- qs[i+1], qs[i+2]);
+ write_q(fd, udp, ssl, buf, (uint16_t)get_random(), proxy_buf,
+ pp2_parsed,
+ qs[i], qs[i+1], qs[i+2]);
/* print at least one result */
if(onarrival) {
wait_results += 1; /* one more answer to fetch */
@@ -390,6 +459,7 @@ send_em(const char* svr, int udp, int usessl, int noanswer, int onarrival,
}
sock_close(fd);
sldns_buffer_free(buf);
+ sldns_buffer_free(proxy_buf);
printf("orderly exit\n");
}
@@ -418,10 +488,11 @@ extern int optind;
extern char* optarg;
/** main program for streamtcp */
-int main(int argc, char** argv)
+int main(int argc, char** argv)
{
int c;
const char* svr = "127.0.0.1";
+ const char* pp2_client = "";
int udp = 0;
int noanswer = 0;
int onarrival = 0;
@@ -451,11 +522,14 @@ int main(int argc, char** argv)
if(argc == 1) {
usage(argv);
}
- while( (c=getopt(argc, argv, "af:hnsud:")) != -1) {
+ while( (c=getopt(argc, argv, "af:p:hnsud:")) != -1) {
switch(c) {
case 'f':
svr = optarg;
break;
+ case 'p':
+ pp2_client = optarg;
+ break;
case 'a':
onarrival = 1;
break;
@@ -508,7 +582,7 @@ int main(int argc, char** argv)
(void)OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL);
#endif
}
- send_em(svr, udp, usessl, noanswer, onarrival, delay, argc, argv);
+ send_em(svr, pp2_client, udp, usessl, noanswer, onarrival, delay, argc, argv);
checklock_stop();
#ifdef USE_WINSOCK
WSACleanup();