From 1a259de1766672f2e5ba8b251e6f25b413c384b0 Mon Sep 17 00:00:00 2001 From: "Todd C. Miller" Date: Mon, 29 Aug 2011 14:10:18 -0400 Subject: [PATCH] Split out address matching into its own file and add regression tests for it. --- MANIFEST | 3 + plugins/sudoers/Makefile.in | 30 ++- plugins/sudoers/match.c | 148 -------------- plugins/sudoers/match_addr.c | 195 +++++++++++++++++++ plugins/sudoers/regress/parser/check_addr.c | 176 +++++++++++++++++ plugins/sudoers/regress/parser/check_addr.in | 13 ++ 6 files changed, 411 insertions(+), 154 deletions(-) create mode 100644 plugins/sudoers/match_addr.c create mode 100644 plugins/sudoers/regress/parser/check_addr.c create mode 100644 plugins/sudoers/regress/parser/check_addr.in diff --git a/MANIFEST b/MANIFEST index b463a5beb..3f689fe8e 100644 --- a/MANIFEST +++ b/MANIFEST @@ -178,6 +178,7 @@ plugins/sudoers/logging.c plugins/sudoers/logging.h plugins/sudoers/logwrap.c plugins/sudoers/match.c +plugins/sudoers/match_addr.c plugins/sudoers/mkdefaults plugins/sudoers/parse.c plugins/sudoers/parse.h @@ -206,6 +207,8 @@ plugins/sudoers/regress/iolog_path/data plugins/sudoers/regress/logging/check_wrap.c plugins/sudoers/regress/logging/check_wrap.in plugins/sudoers/regress/logging/check_wrap.out.ok +plugins/sudoers/regress/parser/check_addr.c +plugins/sudoers/regress/parser/check_addr.in plugins/sudoers/regress/parser/check_fill.c plugins/sudoers/regress/sudoers/test1.in plugins/sudoers/regress/sudoers/test1.out.ok diff --git a/plugins/sudoers/Makefile.in b/plugins/sudoers/Makefile.in index 8220f506f..9ca58ba6c 100644 --- a/plugins/sudoers/Makefile.in +++ b/plugins/sudoers/Makefile.in @@ -106,12 +106,13 @@ SHELL = @SHELL@ PROGS = sudoers.la visudo sudoreplay testsudoers -TEST_PROGS = check_iolog_path check_fill check_wrap +TEST_PROGS = check_iolog_path check_fill check_wrap check_addr AUTH_OBJS = sudo_auth.lo @AUTH_OBJS@ LIBPARSESUDOERS_OBJS = alias.lo audit.lo defaults.lo gram.lo match.lo \ - pwutil.lo timestr.lo toke.lo toke_util.lo redblack.lo + match_addr.lo pwutil.lo timestr.lo toke.lo \ + toke_util.lo redblack.lo SUDOERS_OBJS = $(AUTH_OBJS) boottime.lo check.lo env.lo goodpath.lo \ group_plugin.lo find_path.lo interfaces.lo logging.lo \ @@ -125,11 +126,13 @@ REPLAY_OBJS = getdate.o sudoreplay.o error.o TEST_OBJS = interfaces.o testsudoers.o tsgetgrpw.o error.o group_plugin.o \ net_ifs.o -CHECK_IOLOG_PATH_OBJS = check_iolog_path.o error.o iolog_path.o pwutil.o \ - redblack.o +CHECK_ADDR_OBJS = check_addr.o match_addr.o interfaces.o error.o CHECK_FILL_OBJS = check_fill.o toke_util.o error.o +CHECK_IOLOG_PATH_OBJS = check_iolog_path.o error.o iolog_path.o pwutil.o \ + redblack.o + CHECK_WRAP_OBJS = check_wrap.o logwrap.o error.o LIBOBJDIR = $(top_builddir)/@ac_config_libobj_dir@/ @@ -170,6 +173,9 @@ sudoreplay: $(REPLAY_OBJS) $(LT_LIBS) testsudoers: libparsesudoers.la $(TEST_OBJS) $(LT_LIBS) $(LIBTOOL) --mode=link $(CC) -o $@ $(TEST_OBJS) $(LDFLAGS) libparsesudoers.la $(LIBS) $(NET_LIBS) @LIBDL@ +check_addr: $(CHECK_ADDR_OBJS) $(LT_LIBS) + $(LIBTOOL) --mode=link $(CC) -o $@ $(CHECK_ADDR_OBJS) $(LDFLAGS) $(LIBS) + check_iolog_path: $(CHECK_IOLOG_PATH_OBJS) $(LT_LIBS) $(LIBTOOL) --mode=link $(CC) -o $@ $(CHECK_IOLOG_PATH_OBJS) $(LDFLAGS) $(LIBS) @@ -383,6 +389,9 @@ check.lo: $(srcdir)/check.c $(top_builddir)/config.h $(srcdir)/sudoers.h \ $(srcdir)/defaults.h $(srcdir)/def_data.h $(srcdir)/logging.h \ $(srcdir)/sudo_nss.h $(incdir)/sudo_plugin.h $(incdir)/gettext.h $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/check.c +check_addr.o: $(srcdir)/regress/parser/check_addr.c $(top_builddir)/config.h \ + $(incdir)/list.h $(srcdir)/parse.h $(srcdir)/interfaces.h + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/regress/parser/check_addr.c check_fill.o: $(srcdir)/regress/parser/check_fill.c $(top_builddir)/config.h \ $(incdir)/list.h $(srcdir)/parse.h $(srcdir)/toke.h \ $(srcdir)/gram.h @@ -528,6 +537,15 @@ match.lo: $(srcdir)/match.c $(top_builddir)/config.h $(srcdir)/sudoers.h \ $(srcdir)/interfaces.h $(srcdir)/parse.h $(srcdir)/gram.h \ $(top_srcdir)/compat/fnmatch.h $(top_srcdir)/compat/glob.h $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/match.c +match_addr.lo: $(srcdir)/match_addr.c $(top_builddir)/config.h \ + $(srcdir)/sudoers.h $(top_builddir)/pathnames.h \ + $(incdir)/missing.h $(incdir)/error.h $(incdir)/alloc.h \ + $(incdir)/list.h $(incdir)/fileops.h $(srcdir)/defaults.h \ + $(srcdir)/def_data.h $(srcdir)/logging.h $(srcdir)/sudo_nss.h \ + $(incdir)/sudo_plugin.h $(incdir)/gettext.h \ + $(srcdir)/interfaces.h + $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/match_addr.c +match_addr.o: match_addr.lo net_ifs.o: $(top_srcdir)/src/net_ifs.c $(top_builddir)/config.h \ $(incdir)/missing.h $(incdir)/alloc.h $(incdir)/error.h \ $(incdir)/gettext.h @@ -627,8 +645,8 @@ sudoers.lo: $(srcdir)/sudoers.c $(top_builddir)/config.h $(srcdir)/sudoers.h \ $(incdir)/alloc.h $(incdir)/list.h $(incdir)/fileops.h \ $(srcdir)/defaults.h $(srcdir)/def_data.h $(srcdir)/logging.h \ $(srcdir)/sudo_nss.h $(incdir)/sudo_plugin.h $(incdir)/gettext.h \ - $(incdir)/lbuf.h $(srcdir)/interfaces.h \ - $(srcdir)/sudoers_version.h $(srcdir)/auth/sudo_auth.h + $(srcdir)/interfaces.h $(srcdir)/sudoers_version.h \ + $(srcdir)/auth/sudo_auth.h $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/sudoers.c sudoreplay.o: $(srcdir)/sudoreplay.c $(top_builddir)/config.h \ $(top_srcdir)/compat/timespec.h $(top_builddir)/pathnames.h \ diff --git a/plugins/sudoers/match.c b/plugins/sudoers/match.c index 9a0ccf3f7..9f15020de 100644 --- a/plugins/sudoers/match.c +++ b/plugins/sudoers/match.c @@ -25,7 +25,6 @@ #include #include -#include #include #include #ifdef STDC_HEADERS @@ -57,8 +56,6 @@ #include #include #include -#include -#include #include #ifdef HAVE_DIRENT_H # include @@ -78,7 +75,6 @@ #endif #include "sudoers.h" -#include "interfaces.h" #include "parse.h" #include @@ -597,150 +593,6 @@ command_matches_dir(char *sudoers_dir, size_t dlen) return dent != NULL; } -static int -addr_matches_if(char *n) -{ - union sudo_in_addr_un addr; - struct interface *ifp; -#ifdef HAVE_IN6_ADDR - int j; -#endif - int family; - -#ifdef HAVE_IN6_ADDR - if (inet_pton(AF_INET6, n, &addr.ip6) > 0) { - family = AF_INET6; - } else -#endif - { - family = AF_INET; - addr.ip4.s_addr = inet_addr(n); - } - - for (ifp = interfaces; ifp != NULL; ifp = ifp->next) { - if (ifp->family != family) - continue; - switch(family) { - case AF_INET: - if (ifp->addr.ip4.s_addr == addr.ip4.s_addr || - (ifp->addr.ip4.s_addr & ifp->netmask.ip4.s_addr) - == addr.ip4.s_addr) - return TRUE; - break; -#ifdef HAVE_IN6_ADDR - case AF_INET6: - if (memcmp(ifp->addr.ip6.s6_addr, addr.ip6.s6_addr, - sizeof(addr.ip6.s6_addr)) == 0) - return TRUE; - for (j = 0; j < sizeof(addr.ip6.s6_addr); j++) { - if ((ifp->addr.ip6.s6_addr[j] & ifp->netmask.ip6.s6_addr[j]) != addr.ip6.s6_addr[j]) - break; - } - if (j == sizeof(addr.ip6.s6_addr)) - return TRUE; -#endif - } - } - - return FALSE; -} - -static int -addr_matches_if_netmask(char *n, char *m) -{ - int i; - union sudo_in_addr_un addr, mask; - struct interface *ifp; -#ifdef HAVE_IN6_ADDR - int j; -#endif - int family; - -#ifdef HAVE_IN6_ADDR - if (inet_pton(AF_INET6, n, &addr.ip6) > 0) - family = AF_INET6; - else -#endif - { - family = AF_INET; - addr.ip4.s_addr = inet_addr(n); - } - - if (family == AF_INET) { - if (strchr(m, '.')) { - mask.ip4.s_addr = inet_addr(m); - } else { - i = atoi(m); - if (i == 0) - mask.ip4.s_addr = 0; - else if (i == 32) - mask.ip4.s_addr = 0xffffffff; - else - mask.ip4.s_addr = 0xffffffff - (1 << (32 - i)) + 1; - mask.ip4.s_addr = htonl(mask.ip4.s_addr); - } - addr.ip4.s_addr &= mask.ip4.s_addr; - } -#ifdef HAVE_IN6_ADDR - else { - if (inet_pton(AF_INET6, m, &mask.ip6) <= 0) { - j = atoi(m); - for (i = 0; i < sizeof(addr.ip6.s6_addr); i++) { - if (j < i * 8) - mask.ip6.s6_addr[i] = 0; - else if (i * 8 + 8 <= j) - mask.ip6.s6_addr[i] = 0xff; - else - mask.ip6.s6_addr[i] = 0xff00 >> (j - i * 8); - addr.ip6.s6_addr[i] &= mask.ip6.s6_addr[i]; - } - } - } -#endif /* HAVE_IN6_ADDR */ - - for (ifp = interfaces; ifp != NULL; ifp = ifp->next) { - if (ifp->family != family) - continue; - switch(family) { - case AF_INET: - if ((ifp->addr.ip4.s_addr & mask.ip4.s_addr) == addr.ip4.s_addr) - return TRUE; -#ifdef HAVE_IN6_ADDR - case AF_INET6: - for (j = 0; j < sizeof(addr.ip6.s6_addr); j++) { - if ((ifp->addr.ip6.s6_addr[j] & mask.ip6.s6_addr[j]) != addr.ip6.s6_addr[j]) - break; - } - if (j == sizeof(addr.ip6.s6_addr)) - return TRUE; -#endif /* HAVE_IN6_ADDR */ - } - } - - return FALSE; -} - -/* - * Returns TRUE if "n" is one of our ip addresses or if - * "n" is a network that we are on, else returns FALSE. - */ -int -addr_matches(char *n) -{ - char *m; - int retval; - - /* If there's an explicit netmask, use it. */ - if ((m = strchr(n, '/'))) { - *m++ = '\0'; - retval = addr_matches_if_netmask(n, m); - *(m - 1) = '/'; - } else - retval = addr_matches_if(n); - - return retval; -} - /* * Returns TRUE if the hostname matches the pattern, else FALSE */ diff --git a/plugins/sudoers/match_addr.c b/plugins/sudoers/match_addr.c new file mode 100644 index 000000000..f4bc73150 --- /dev/null +++ b/plugins/sudoers/match_addr.c @@ -0,0 +1,195 @@ +/* + * Copyright (c) 1996, 1998-2005, 2007-2011 + * Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Sponsored in part by the Defense Advanced Research Projects + * Agency (DARPA) and Air Force Research Laboratory, Air Force + * Materiel Command, USAF, under agreement number F39502-99-1-0512. + */ + +#include + +#include +#include +#include +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif /* STDC_HEADERS */ +#ifdef HAVE_STRING_H +# include +#endif /* HAVE_STRING_H */ +#ifdef HAVE_STRINGS_H +# include +#endif /* HAVE_STRINGS_H */ +#ifdef HAVE_UNISTD_H +# include +#endif /* HAVE_UNISTD_H */ +#include +#include +#include + +#include "sudoers.h" +#include "interfaces.h" + +static int +addr_matches_if(char *n) +{ + union sudo_in_addr_un addr; + struct interface *ifp; +#ifdef HAVE_IN6_ADDR + int j; +#endif + int family; + +#ifdef HAVE_IN6_ADDR + if (inet_pton(AF_INET6, n, &addr.ip6) > 0) { + family = AF_INET6; + } else +#endif + { + family = AF_INET; + addr.ip4.s_addr = inet_addr(n); + } + + for (ifp = interfaces; ifp != NULL; ifp = ifp->next) { + if (ifp->family != family) + continue; + switch(family) { + case AF_INET: + if (ifp->addr.ip4.s_addr == addr.ip4.s_addr || + (ifp->addr.ip4.s_addr & ifp->netmask.ip4.s_addr) + == addr.ip4.s_addr) + return TRUE; + break; +#ifdef HAVE_IN6_ADDR + case AF_INET6: + if (memcmp(ifp->addr.ip6.s6_addr, addr.ip6.s6_addr, + sizeof(addr.ip6.s6_addr)) == 0) + return TRUE; + for (j = 0; j < sizeof(addr.ip6.s6_addr); j++) { + if ((ifp->addr.ip6.s6_addr[j] & ifp->netmask.ip6.s6_addr[j]) != addr.ip6.s6_addr[j]) + break; + } + if (j == sizeof(addr.ip6.s6_addr)) + return TRUE; +#endif + } + } + + return FALSE; +} + +static int +addr_matches_if_netmask(char *n, char *m) +{ + int i; + union sudo_in_addr_un addr, mask; + struct interface *ifp; +#ifdef HAVE_IN6_ADDR + int j; +#endif + int family; + +#ifdef HAVE_IN6_ADDR + if (inet_pton(AF_INET6, n, &addr.ip6) > 0) + family = AF_INET6; + else +#endif + { + family = AF_INET; + addr.ip4.s_addr = inet_addr(n); + } + + if (family == AF_INET) { + if (strchr(m, '.')) { + mask.ip4.s_addr = inet_addr(m); + } else { + i = atoi(m); + if (i == 0) + mask.ip4.s_addr = 0; + else if (i == 32) + mask.ip4.s_addr = 0xffffffff; + else + mask.ip4.s_addr = 0xffffffff - (1 << (32 - i)) + 1; + mask.ip4.s_addr = htonl(mask.ip4.s_addr); + } + addr.ip4.s_addr &= mask.ip4.s_addr; + } +#ifdef HAVE_IN6_ADDR + else { + if (inet_pton(AF_INET6, m, &mask.ip6) <= 0) { + j = atoi(m); + for (i = 0; i < sizeof(addr.ip6.s6_addr); i++) { + if (j < i * 8) + mask.ip6.s6_addr[i] = 0; + else if (i * 8 + 8 <= j) + mask.ip6.s6_addr[i] = 0xff; + else + mask.ip6.s6_addr[i] = 0xff00 >> (j - i * 8); + addr.ip6.s6_addr[i] &= mask.ip6.s6_addr[i]; + } + } + } +#endif /* HAVE_IN6_ADDR */ + + for (ifp = interfaces; ifp != NULL; ifp = ifp->next) { + if (ifp->family != family) + continue; + switch(family) { + case AF_INET: + if ((ifp->addr.ip4.s_addr & mask.ip4.s_addr) == addr.ip4.s_addr) + return TRUE; +#ifdef HAVE_IN6_ADDR + case AF_INET6: + for (j = 0; j < sizeof(addr.ip6.s6_addr); j++) { + if ((ifp->addr.ip6.s6_addr[j] & mask.ip6.s6_addr[j]) != addr.ip6.s6_addr[j]) + break; + } + if (j == sizeof(addr.ip6.s6_addr)) + return TRUE; +#endif /* HAVE_IN6_ADDR */ + } + } + + return FALSE; +} + +/* + * Returns TRUE if "n" is one of our ip addresses or if + * "n" is a network that we are on, else returns FALSE. + */ +int +addr_matches(char *n) +{ + char *m; + int retval; + + /* If there's an explicit netmask, use it. */ + if ((m = strchr(n, '/'))) { + *m++ = '\0'; + retval = addr_matches_if_netmask(n, m); + *(m - 1) = '/'; + } else + retval = addr_matches_if(n); + + return retval; +} diff --git a/plugins/sudoers/regress/parser/check_addr.c b/plugins/sudoers/regress/parser/check_addr.c new file mode 100644 index 000000000..65f7099bc --- /dev/null +++ b/plugins/sudoers/regress/parser/check_addr.c @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2011 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include +#include +#include +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif /* STDC_HEADERS */ +#include +#ifdef HAVE_STRING_H +# include +#endif /* HAVE_STRING_H */ +#ifdef HAVE_STRINGS_H +# include +#endif /* HAVE_STRINGS_H */ +#include +#include +#include +#include + +#include +#include +#include + +#include "sudoers.h" +#include "parse.h" +#include "interfaces.h" + +static int check_addr_printf(int msg_type, const char *fmt, ...); + +/* for match_addr.c */ +struct interface *interfaces; +sudo_printf_t sudo_printf = check_addr_printf; + +static int +check_addr(char *input) +{ + int expected, matched; + size_t len; + char *cp; + + while (isspace((unsigned char)*input)) + input++; + + /* input: "addr[/mask] 1/0" */ + len = strcspn(input, " \t"); + cp = input + len; + while (isspace((unsigned char)*cp)) + cp++; + expected = atoi(cp); + input[len] = '\0'; + + matched = addr_matches(input); + warningx("%s %smatched (%s)", input, matched ? "" : "not ", + matched == expected ? "OK" : "FAIL"); + return (matched != expected); +} + +static void +usage(void) +{ + fprintf(stderr, "usage: check_addr datafile\n"); + exit(1); +} + +int +main(int argc, char *argv[]) +{ + int ntests = 0, errors = 0; + char *cp, line[2048]; + size_t len; + FILE *fp; + + if (argc != 2) + usage(); + + fp = fopen(argv[1], "r"); + if (fp == NULL) + errorx(1, "unable to open %s", argv[1]); + + /* + * Input is in the following format. There are two types of + * lines: interfaces, which sets the address and mask of the + * locally connected ethernet interfaces for the lines that + * follow and, address lines that include and address (with + * optional netmask) to match, followed by expected match status + * (1 or 0). E.g. + * + * interfaces: addr1/mask addr2/mask ... + * address: addr[/mask] 1/0 + * address: addr[/mask] 1/0 + * interfaces: addr3/mask addr4/mask ... + * address: addr[/mask] 1/0 + */ + + while (fgets(line, sizeof(line), fp) != NULL) { + len = strcspn(line, "\n"); + line[len] = '\0'; + + /* Ignore comments */ + if ((cp = strchr(line, '#')) != NULL) + *cp = '\0'; + + /* Skip blank lines. */ + if (line[0] == '\0') + continue; + + if (strncmp(line, "interfaces:", sizeof("interfaces:") - 1) == 0) { + set_interfaces(line + sizeof("interfaces:") - 1); + } else if (strncmp(line, "address:", sizeof("address:") - 1) == 0) { + errors += check_addr(line + sizeof("address:") - 1); + ntests++; + } else { + warningx("unexpected data line: %s\n", line); + continue; + } + } + + printf("check_addr: %d tests run, %d errors, %d%% success rate\n", + ntests, errors, (ntests - errors) * 100 / ntests); + + exit(errors); +} + +/* STUB */ +void +cleanup(int gotsig) +{ + return; +} + +static int +check_addr_printf(int msg_type, const char *fmt, ...) +{ + va_list ap; + FILE *fp; + + switch (msg_type) { + case SUDO_CONV_INFO_MSG: + fp = stdout; + break; + case SUDO_CONV_ERROR_MSG: + fp = stderr; + break; + default: + errno = EINVAL; + return -1; + } + + va_start(ap, fmt); + vfprintf(fp, fmt, ap); + va_end(ap); + + return 0; +} diff --git a/plugins/sudoers/regress/parser/check_addr.in b/plugins/sudoers/regress/parser/check_addr.in new file mode 100644 index 000000000..a3c86128a --- /dev/null +++ b/plugins/sudoers/regress/parser/check_addr.in @@ -0,0 +1,13 @@ +# +interfaces: 10.5.54.73/255.255.240.0 +address: 10.5.48.0 1 +address: 10.5.54.0/20 1 +# +interfaces: 128.138.243.151/255.255.255.0 128.138.241.53/255.255.255.0 +address: 128.138.243.0 1 +address: 128.138.243.0/24 1 +address: 128.138.241.0 1 +address: 128.138.241.0/24 1 +address: 128.138.242.0/24 0 +address: 128.138.0.0 0 +address: 128.138.0.0/16 1