diff --git a/configure.ac b/configure.ac index 6c73391afa..cdbd48fe3c 100755 --- a/configure.ac +++ b/configure.ac @@ -381,6 +381,8 @@ AC_ARG_ENABLE(cumulus, AS_HELP_STRING([--enable-cumulus], [enable Cumulus Switch Special Extensions])) AC_ARG_ENABLE(datacenter, AS_HELP_STRING([--enable-datacenter], [enable Compilation for Data Center Extensions])) +AC_ARG_ENABLE(fuzzing, + AS_HELP_STRING([--enable-fuzzing], [enable ability to fuzz various parts of FRR])) AC_ARG_ENABLE(rr-semantics, AS_HELP_STRING([--disable-rr-semantics], [disable the v6 Route Replace semantics])) AC_ARG_ENABLE([protobuf], @@ -434,6 +436,10 @@ else DFLT_NAME="traditional" fi +if test "${enable_fuzzing}" = "yes" ; then + AC_DEFINE(HANDLE_ZAPI_FUZZING,,Compile extensions to use with a fuzzer) +fi + if test "${enable_cumulus}" = "yes" ; then AC_DEFINE(HAVE_CUMULUS,,Compile Special Cumulus Code in) fi diff --git a/doc/install.texi b/doc/install.texi index 1930af95e6..19d9614420 100644 --- a/doc/install.texi +++ b/doc/install.texi @@ -101,6 +101,10 @@ needs libexecinfo, while on glibc support for this is part of libc itself. Turn on some options for compiling FRR within a development environment in mind. Specifically turn on -g3 -O0 for compiling options and add inclusion of grammar sandbox. +@item --enable-fuzzing +Turn on some compile options to allow you to run fuzzing tools +against the system. This tools is intended as a developer +only tool and should not be used for normal operations @end table You may specify any combination of the above options to the configure diff --git a/zebra/main.c b/zebra/main.c index cf677a7753..36c931c4ee 100644 --- a/zebra/main.c +++ b/zebra/main.c @@ -201,6 +201,9 @@ int main(int argc, char **argv) char *lblmgr_path = NULL; struct sockaddr_storage dummy; socklen_t dummylen; +#if defined(HANDLE_ZAPI_FUZZING) + char *fuzzing = NULL; +#endif frr_preinit(&zebra_di, argc, argv); @@ -208,6 +211,9 @@ int main(int argc, char **argv) "bakz:e:l:r" #ifdef HAVE_NETLINK "s:" +#endif +#if defined(HANDLE_ZAPI_FUZZING) + "c:" #endif , longopts, @@ -221,6 +227,9 @@ int main(int argc, char **argv) #ifdef HAVE_NETLINK " -s, --nl-bufsize Set netlink receive buffer size\n" #endif /* HAVE_NETLINK */ +#if defined(HANDLE_ZAPI_FUZZING) + " -c Bypass normal startup use this file for tetsting of zapi" +#endif ); while (1) { @@ -271,6 +280,11 @@ int main(int argc, char **argv) nl_rcvbufsize = atoi(optarg); break; #endif /* HAVE_NETLINK */ +#if defined(HANDLE_ZAPI_FUZZING) + case 'c': + fuzzing = optarg; + break; +#endif default: frr_help_exit(1); break; @@ -308,6 +322,13 @@ int main(int argc, char **argv) * routing socket. */ zebra_ns_init(); +#if defined(HANDLE_ZAPI_FUZZING) + if (fuzzing) { + zserv_read_file(fuzzing); + exit(0); + } +#endif + /* Process the configuration file. Among other configuration * directives we can meet those installing static routes. Such * requests will not be executed immediately, but queued in diff --git a/zebra/zserv.c b/zebra/zserv.c index 9d9a7cd783..2389944e84 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -2562,6 +2562,26 @@ static inline void zserv_handle_commands(struct zserv *client, } } +#if defined(HANDLE_ZAPI_FUZZING) +static void zserv_write_incoming(struct stream *orig, uint16_t command) +{ + char fname[MAXPATHLEN]; + struct stream *copy; + int fd = -1; + + copy = stream_dup(orig); + stream_set_getp(copy, 0); + + zserv_privs.change(ZPRIVS_RAISE); + snprintf(fname, MAXPATHLEN, "%s/%u", DAEMON_VTY_DIR, command); + fd = open(fname, O_CREAT | O_WRONLY | O_EXCL, 0644); + stream_flush(copy, fd); + close(fd); + zserv_privs.change(ZPRIVS_LOWER); + stream_free(copy); +} +#endif + /* Handler of zebra service request. */ static int zebra_client_read(struct thread *thread) { @@ -2572,7 +2592,11 @@ static int zebra_client_read(struct thread *thread) uint8_t marker, version; vrf_id_t vrf_id; struct zebra_vrf *zvrf; +#if defined(HANDLE_ZAPI_FUZZING) + int packets = 1; +#else int packets = zebrad.packets_to_process; +#endif /* Get thread data. Reset reading thread because I'm running. */ sock = THREAD_FD(thread); @@ -2662,6 +2686,9 @@ static int zebra_client_read(struct thread *thread) } } +#if defined(HANDLE_ZAPI_FUZZING) + zserv_write_incoming(client->ibuf, command); +#endif length -= ZEBRA_HEADER_SIZE; /* Debug packet information. */ @@ -3209,6 +3236,26 @@ static struct cmd_node forwarding_node = {FORWARDING_NODE, "", /* This node has no interface. */ 1}; +#if defined(HANDLE_ZAPI_FUZZING) +void zserv_read_file(char *input) +{ + int fd; + struct zserv *client = NULL; + struct thread t; + + zebra_client_create(-1); + client = zebrad.client_list->head->data; + t.arg = client; + + fd = open(input, O_RDONLY|O_NONBLOCK); + t.u.fd = fd; + + zebra_client_read(&t); + + close(fd); +} +#endif + /* Initialisation of zebra and installation of commands. */ void zebra_init(void) { diff --git a/zebra/zserv.h b/zebra/zserv.h index 279b56ec3c..60e055088a 100644 --- a/zebra/zserv.h +++ b/zebra/zserv.h @@ -193,4 +193,8 @@ extern int zebra_server_send_message(struct zserv *client); extern struct zserv *zebra_find_client(u_char proto); +#if defined(HANDLE_ZAPI_FUZZING) +extern void zserv_read_file(char *input); +#endif + #endif /* _ZEBRA_ZEBRA_H */