Trinity is a syscall fuzz tool for local host testing. But it would also be
very useful to fuzz during established sessions over the network. This patch
add simple connection ability for IPv4/IPv6 so user can use it as a
client/server and simulate as a real environment.

Signed-off-by: Hangbin Liu <[email protected]>
---
 include/net.h    |  2 ++
 include/params.h |  3 +++
 net/proto-ipv4.c | 13 +++++++++++++
 net/proto-ipv6.c | 14 ++++++++++++++
 params.c         | 25 +++++++++++++++++++++----
 5 files changed, 53 insertions(+), 4 deletions(-)

diff --git a/include/net.h b/include/net.h
index 15c51a6..d7a0f0f 100644
--- a/include/net.h
+++ b/include/net.h
@@ -13,6 +13,8 @@ extern unsigned int nr_sockets;
 /* protocol decoding */
 extern unsigned int specific_proto;
 
+extern int server_port;
+extern char server_addr[INET6_ADDRSTRLEN];
 
 /* glibc headers might be older than the kernel, so chances are we know
  * about more protocols than glibc does. So we define our own PF_MAX */
diff --git a/include/params.h b/include/params.h
index 2ee0f7b..40d213e 100644
--- a/include/params.h
+++ b/include/params.h
@@ -52,3 +52,6 @@ extern unsigned int kernel_taint_mask;
 extern bool kernel_taint_param_occured;
 
 extern unsigned int user_specified_children;
+
+extern int server_port;
+extern char server_addr[INET6_ADDRSTRLEN];
diff --git a/net/proto-ipv4.c b/net/proto-ipv4.c
index 8babe6d..976197f 100644
--- a/net/proto-ipv4.c
+++ b/net/proto-ipv4.c
@@ -85,12 +85,25 @@ in_addr_t random_ipv4_address(void)
 void ipv4_gen_sockaddr(struct sockaddr **addr, socklen_t *addrlen)
 {
        struct sockaddr_in *ipv4;
+       struct in_addr serv_addr;
 
        ipv4 = zmalloc(sizeof(struct sockaddr_in));
 
        ipv4->sin_family = PF_INET;
        ipv4->sin_addr.s_addr = random_ipv4_address();
        ipv4->sin_port = htons(rand() % 65535);
+
+       /* Client side if we supplied server_addr */
+       if (inet_pton(PF_INET, server_addr, &serv_addr) == 1)
+               ipv4->sin_addr = serv_addr;
+       /* Server side if we supplied port without addr, so listen on 
INADDR_ANY */
+       else if (server_port != 0)
+               ipv4->sin_addr.s_addr = htonl(INADDR_ANY);
+
+       /* Fuzz from port to (port + 100) if supplied */
+       if (server_port != 0)
+               ipv4->sin_port = htons(server_port + rand() % 100);
+
        *addr = (struct sockaddr *) ipv4;
        *addrlen = sizeof(struct sockaddr_in);
 }
diff --git a/net/proto-ipv6.c b/net/proto-ipv6.c
index 16bceb3..bf62897 100644
--- a/net/proto-ipv6.c
+++ b/net/proto-ipv6.c
@@ -5,6 +5,7 @@
 #include <linux/if.h>
 #include <linux/if_arp.h>
 #include <linux/if_packet.h>
+#include <arpa/inet.h>
 #include <stdlib.h>
 #include "net.h"
 #include "random.h"
@@ -14,6 +15,7 @@
 void ipv6_gen_sockaddr(struct sockaddr **addr, socklen_t *addrlen)
 {
        struct sockaddr_in6 *ipv6;
+       struct in6_addr serv_addr;
 
        ipv6 = zmalloc(sizeof(struct sockaddr_in6));
 
@@ -23,6 +25,18 @@ void ipv6_gen_sockaddr(struct sockaddr **addr, socklen_t 
*addrlen)
        ipv6->sin6_addr.s6_addr32[2] = 0;
        ipv6->sin6_addr.s6_addr32[3] = htonl(1);
        ipv6->sin6_port = htons(rand() % 65535);
+
+       /* Client side if we supplied server_addr */
+       if (inet_pton(PF_INET6, server_addr, &serv_addr) == 1)
+               ipv6->sin6_addr = serv_addr;
+       /* Server side if we supplied port without addr, so listen on 
in6addr_any */
+       else if (server_port != 0)
+               ipv6->sin6_addr = in6addr_any;
+
+       /* Fuzz from port to (port + 100) if supplied */
+       if (server_port != 0)
+               ipv6->sin6_port = htons(server_port + rand() % 100);
+
        *addr = (struct sockaddr *) ipv6;
        *addrlen = sizeof(struct sockaddr_in6);
 }
diff --git a/params.c b/params.c
index df702e3..c8eef3a 100644
--- a/params.c
+++ b/params.c
@@ -57,6 +57,9 @@ char *victim_path = NULL;
 unsigned int kernel_taint_mask = 0xFFFFFFFF;
 bool kernel_taint_param_occured = FALSE;
 
+int server_port = 0;
+char server_addr[INET6_ADDRSTRLEN] = "\0";
+
 static void usage(void)
 {
        outputerr("%s\n", progname);
@@ -77,6 +80,8 @@ static void usage(void)
        outputerr(" --no_proto,-E: specify network protocols to be excluded 
from testing.\n");
        outputerr(" --quiet,-q: less output.\n");
        outputerr(" --random,-r#: pick N syscalls at random and just fuzz 
those\n");
+       outputerr(" --server_addr: supply an IPv4 or IPv6 address to connect, 
no need for server side.\n");
+       outputerr(" --server_port: supply an server port to listen or connect, 
will fuzz between port to (port + 100)\n");
        outputerr(" --syslog,-S: log important info to syslog. (useful if 
syslog is remote)\n");
        outputerr(" --verbose,-v: increase output verbosity.\n");
        outputerr(" --victims,-V: path to victim files.\n");
@@ -110,6 +115,8 @@ static const struct option longopts[] = {
        { "proto", required_argument, NULL, 'P' },
        { "quiet", no_argument, NULL, 'q' },
        { "random", required_argument, NULL, 'r' },
+       { "server_addr", required_argument, NULL, 0 },
+       { "server_port", required_argument, NULL, 0 },
        { "syslog", no_argument, NULL, 'S' },
        { "verbose", no_argument, NULL, 'v' },
        { "victims", required_argument, NULL, 'V' },
@@ -118,8 +125,9 @@ static const struct option longopts[] = {
 void parse_args(int argc, char *argv[])
 {
        int opt;
+       int opt_index = 0;
 
-       while ((opt = getopt_long(argc, argv, paramstr, longopts, NULL)) != -1) 
{
+       while ((opt = getopt_long(argc, argv, paramstr, longopts, &opt_index)) 
!= -1) {
                switch (opt) {
                default:
                        if (opt == '?')
@@ -128,9 +136,6 @@ void parse_args(int argc, char *argv[])
                                outputstd("opt:%c\n", opt);
                        return;
 
-               case '\0':
-                       return;
-
                case 'b':
                        init_bdev_list();
                        process_bdev_param(optarg);
@@ -294,6 +299,18 @@ void parse_args(int argc, char *argv[])
                case 'X':
                        dropprivs = TRUE;
                        break;
+
+               case 0:
+                       /*
+                        * FIXME: It's really hard to find two reasonable short
+                        * names since S s P p all have been used. Use long
+                        * options before we fix this issue.
+                       */
+                       if (strcmp("server_addr", longopts[opt_index].name) == 
0)
+                               strcpy(server_addr, optarg);
+                       if (strcmp("server_port", longopts[opt_index].name) == 
0)
+                               server_port = atoi(optarg);
+                       break;
                }
        }
        if (quiet_level > MAX_LOGLEVEL)
-- 
1.9.3

--
To unsubscribe from this list: send the line "unsubscribe trinity" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to