diff options
author | Bjørn Mork <bjorn@mork.no> | 2015-05-15 10:25:07 +0200 |
---|---|---|
committer | Bjørn Mork <bjorn@mork.no> | 2015-05-15 10:25:07 +0200 |
commit | 35294332b2e75151b4b614719ee6522e1afd8748 (patch) | |
tree | fde51b865f9a08ebd3ef87bc382dec5bb165f4c9 /networking | |
parent | 02013228914a1d17e8df15d4e2b7950469395a5c (diff) |
ripe-atlas-fw: imported version 45504550
Signed-off-by: Bjørn Mork <bjorn@mork.no>
Diffstat (limited to 'networking')
-rw-r--r-- | networking/Config.in | 6 | ||||
-rw-r--r-- | networking/Kbuild | 1 | ||||
-rw-r--r-- | networking/httppost.c | 9 | ||||
-rw-r--r-- | networking/route.c | 2 | ||||
-rw-r--r-- | networking/rptaddr6.c | 493 | ||||
-rw-r--r-- | networking/rptra6.c | 2 |
6 files changed, 511 insertions, 2 deletions
diff --git a/networking/Config.in b/networking/Config.in index 7c72b6d..cdf067a 100644 --- a/networking/Config.in +++ b/networking/Config.in @@ -705,6 +705,12 @@ config RPTRA6 help Report received IPv6 router advertisements +config RPTADDR6 + bool "rptaddr6" + default n + help + Report IPv6 addresses and routes + config RXTXRPT bool "rxtxrpt" default n diff --git a/networking/Kbuild b/networking/Kbuild index ff7dfb3..ddb143a 100644 --- a/networking/Kbuild +++ b/networking/Kbuild @@ -32,6 +32,7 @@ lib-$(CONFIG_PING6) += ping.o lib-$(CONFIG_PSCAN) += pscan.o lib-$(CONFIG_ROUTE) += route.o lib-$(CONFIG_RPTRA6) += rptra6.o +lib-$(CONFIG_RPTADDR6) += rptaddr6.o lib-$(CONFIG_RXTXRPT) += rxtxrpt.o lib-$(CONFIG_SLATTACH) += slattach.o lib-$(CONFIG_SSLGETCERT) += sslgetcert.o diff --git a/networking/httppost.c b/networking/httppost.c index 26934ec..6b8b533 100644 --- a/networking/httppost.c +++ b/networking/httppost.c @@ -150,6 +150,15 @@ int httppost_main(int argc, char *argv[]) } url= argv[optind]; + if (atlas_id) + { + if (!validate_atlas_id(atlas_id)) + { + fprintf(stderr, "bad atlas ID '%s'", atlas_id); + return 1; + } + } + if (maxpostsizestr) { maxpostsize= strtoul(maxpostsizestr, &check, 0); diff --git a/networking/route.c b/networking/route.c index 8778ecd..b040539 100644 --- a/networking/route.c +++ b/networking/route.c @@ -462,7 +462,7 @@ static const char flagchars[] ALIGN1 = #endif ; -static void set_flags(char *flagstr, int flags) +void set_flags(char *flagstr, int flags) { int i; diff --git a/networking/rptaddr6.c b/networking/rptaddr6.c new file mode 100644 index 0000000..9c60425 --- /dev/null +++ b/networking/rptaddr6.c @@ -0,0 +1,493 @@ +/* + * rptaddr6.c + * Copyright (c) 2013 RIPE NCC <atlas@ripe.net> + * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. + */ + +#include <errno.h> +#include <stdarg.h> +#include <stdio.h> +#include <string.h> +#include <net/route.h> +#include <inet_common.h> +#include "../eperd/eperd.h" + +#include "libbb.h" + +#define IF_INET6_FILE "/proc/net/if_inet6" +#define IPV6_ROUTE_FILE "/proc/net/ipv6_route" +#define SUFFIX ".new" + +#define SAFE_PREFIX_O ATLAS_DATA_OUT +#define SAFE_PREFIX_N ATLAS_DATA_NEW + +#define OPT_STRING "A:O:c:" + +#define DBQ(str) "\"" #str "\"" +#define JS(key, val) fprintf(fh, "\"" #key"\" : \"%s\" , ", val); +#define JS1(key, fmt, val) fprintf(fh, "\"" #key"\" : "#fmt" , ", val); + +#ifndef IPV6_MASK +#define IPV6_MASK (RTF_GATEWAY|RTF_HOST|RTF_DEFAULT|RTF_ADDRCONF|RTF_CACHE) +#endif + +#define IPV6_ADDR_LOOPBACK 0x0010U +#define IPV6_ADDR_LINKLOCAL 0x0020U +#define IPV6_ADDR_SITELOCAL 0x0040U + +#define IPV6_ADDR_COMPATv4 0x0080U + +#define IPV6_ADDR_SCOPE_MASK 0x00f0U + +enum { + OPT_a = (1 << 0), +}; + +static int setup_ipv6_rpt(char *cache_name, int *need_report); +static int rpt_ipv6(char *cache_name, char *out_name, char *opt_atlas, int opt_append); +static void report(const char *fmt, ...); +static void report_err(const char *fmt, ...); + +int rptaddr6_main(int argc, char *argv[]) +{ + int r, need_report; + unsigned opt; + char *opt_atlas; + char *cache_name; /* temp file in an intermediate format */ + char *out_name; /* output file in json: timestamp opt_atlas */ + int opt_append; + + opt_atlas= NULL; + out_name = NULL; + cache_name = NULL; + opt_atlas = NULL; + opt_complementary= NULL; + opt_append = FALSE; + + opt= getopt32(argv, OPT_STRING, &opt_atlas, &out_name, &cache_name); + + if (out_name && !validate_filename(out_name, SAFE_PREFIX_O)) + { + crondlog(LVL8 "insecure file '%s' : allowed '%s'", out_name, + SAFE_PREFIX_O); + return 1; + } + if (cache_name && !validate_filename(cache_name, SAFE_PREFIX_N)) + { + crondlog(LVL8 "insecure file '%s' allowed %s", cache_name, + SAFE_PREFIX_N); + return 1; + } + + if (!cache_name) { + crondlog(LVL8 "missing requried option, -c <cache_file>"); + return 1; + } + + if (opt & OPT_a) + opt_append = TRUE; + + r= setup_ipv6_rpt(cache_name, &need_report); + if (r != 0) + return r; + if (need_report) + { + r = rpt_ipv6(cache_name, out_name, opt_atlas, opt_append); + if (r != 0) + return r; + } + + return 0; +} +static int setup_ipv6_rpt(char *cache_name, int *need_report) +{ + int i, r, n; + char *cp, *cp1; + char filename[80]; + char dst6in[INET6_ADDRSTRLEN]; + char nh6in[INET6_ADDRSTRLEN]; /* next hop */ + char *dst6out = NULL; + char *nh6out = NULL; + char dst6p[8][5]; + char nh6p[8][5]; + char iface[16], flags[16]; + char Scope[32]; + int scope, dad_status, if_idx; + int iflags, metric, refcnt, use, prefix_len, slen; + struct sockaddr_in6 sdst6, snh6; + + char buf1[1024]; + char buf2[1024]; + FILE *in_file, *out_file, *cache_file; + + *need_report= 0; + + if (strlen(cache_name) + strlen(SUFFIX) + 1 > sizeof(filename)) + { + report("cache name '%s' too long", cache_name); + return 1; + } + + strlcpy(filename, cache_name, sizeof(filename)); + strlcat(filename, SUFFIX, sizeof(filename)); + + out_file= fopen(filename, "w"); + if (out_file == NULL) + { + report_err("unable to create '%s'", filename); + return 1; + } + + /* Copy IF_INET6_FILE */ + in_file= fopen(IF_INET6_FILE, "r"); + if (in_file == NULL) + { + report_err("unable to open '%s'", IF_INET6_FILE); + fclose(out_file); + return 1; + } + n = 0; + while ((r = fscanf(in_file, "%4s%4s%4s%4s%4s%4s%4s%4s %08x %02x %02x %02x %20s\n", + dst6p[0], dst6p[1], dst6p[2] + , dst6p[3], dst6p[4], dst6p[5] + , dst6p[6], dst6p[7], &if_idx, &prefix_len + , &scope, &dad_status, iface)) != EOF) { + + snprintf(dst6in, sizeof(dst6in), "%s:%s:%s:%s:%s:%s:%s:%s", + dst6p[0], dst6p[1], dst6p[2], dst6p[3], + dst6p[4], dst6p[5], dst6p[6], dst6p[7]); + + inet_pton(AF_INET6, dst6in, (struct sockaddr *) &sdst6.sin6_addr); + sdst6.sin6_family = AF_INET6; + dst6out = INET6_rresolve((struct sockaddr_in6 *) &sdst6, 0x0fff); + + switch (scope & IPV6_ADDR_SCOPE_MASK) { + case 0: + snprintf(Scope, sizeof(Scope), "Global"); + break; + case IPV6_ADDR_LINKLOCAL: + snprintf(Scope, sizeof(Scope), "Link"); + break; + case IPV6_ADDR_SITELOCAL: + snprintf(Scope, sizeof(Scope), "Site"); + break; + case IPV6_ADDR_COMPATv4: + snprintf(Scope, sizeof(Scope), "Compat"); + break; + case IPV6_ADDR_LOOPBACK: + snprintf(Scope, sizeof(Scope), "Host"); + break; + default: + snprintf(Scope, sizeof(Scope), "Unknown %d", scope); + } + r = snprintf(buf2, sizeof(buf2), "%s %s{" DBQ(inet6 addr) " : " + DBQ(%s) ", " DBQ(prefix length) " : %d," + DBQ(scope) " : " DBQ(%s) ", " DBQ(interface) + " : " DBQ(%s) "}", + n ? "" : "\"inet6 addresses\" : [", n ? ", " : "" + , dst6out, prefix_len, Scope, iface); + + /* printf("%s\n", buf2); */ + + if(dst6out) { + free(dst6out); + dst6out=NULL; + } + n++; + if (fwrite(buf2, 1, r, out_file) != r) + { + report_err("error writing to '%s'", filename); + fclose(in_file); + fclose(out_file); + return 1; + } + + if (ferror(in_file)) + { + report_err("error reading from '%s'", IF_INET6_FILE); + fclose(in_file); + fclose(out_file); + return 1; + } + } + if ( n > 0 ) { + r = snprintf(buf2, 2, "]"); + } + if (fwrite(buf2, 1, r, out_file) != r) + { + report_err("error writing to '%s'", filename); + fclose(in_file); + fclose(out_file); + return 1; + } + + fclose(in_file); + + /* Copy IPV6_ROUTE_FILE */ + in_file= fopen(IPV6_ROUTE_FILE, "r"); + if (in_file == NULL) + { + report_err("unable to open '%s'", IPV6_ROUTE_FILE); + fclose(out_file); + return 1; + } + + n = 0; + while ((r = fscanf (in_file, "%4s%4s%4s%4s%4s%4s%4s%4s%x%*s%x%4s%4s%4s%4s%4s%4s%4s%4s%x%x%x%x%s\n", + dst6p[0], dst6p[1], dst6p[2], dst6p[3], dst6p[4], + dst6p[5], dst6p[6], dst6p[7], &prefix_len, &slen, + nh6p[0], nh6p[1], nh6p[2], nh6p[3], nh6p[4], + nh6p[5], nh6p[6], nh6p[7], &metric, &use, &refcnt, &iflags, iface)) != EOF) { + + if (r != 23) { + if ((r < 0) && feof(in_file)) { /* EOF with no (nonspace) chars read. */ + break; + } + report_err("reading '%s'", IF_INET6_FILE); + fclose(in_file); + fclose(out_file); + return 1; + } + + /* skip some the stuff we don't want to report */ + if (!(iflags & RTF_UP)) { /* Skip interfaces that are down. */ + continue; + } + if ((iflags & RTF_ADDRCONF) && (iflags & RTF_CACHE)) { /* Skip interfaces that are down. */ + continue; + } + + if ( strncmp (dst6p[0], "ff02", strlen("ff02")) == 0 ) { + continue; + } + if ( strncmp (dst6p[0], "ff00", strlen("ff00")) == 0 ) { + continue; + } + + snprintf(dst6in, sizeof(dst6in), "%s:%s:%s:%s:%s:%s:%s:%s", + dst6p[0], dst6p[1], dst6p[2], dst6p[3], + dst6p[4], dst6p[5], dst6p[6], dst6p[7]); + + snprintf(nh6in, sizeof(nh6in), "%s:%s:%s:%s:%s:%s:%s:%s", + nh6p[0], nh6p[1], nh6p[2], nh6p[3], + nh6p[4], nh6p[5], nh6p[6], nh6p[7]); + + + set_flags(flags, (iflags & IPV6_MASK)); + inet_pton(AF_INET6, dst6in, (struct sockaddr *) &sdst6.sin6_addr); + sdst6.sin6_family = AF_INET6; + dst6out = INET6_rresolve((struct sockaddr_in6 *) &sdst6, 0x0fff); + + inet_pton(AF_INET6, nh6in, (struct sockaddr *) &snh6.sin6_addr); + snh6.sin6_family = AF_INET6; + nh6out = INET6_rresolve((struct sockaddr_in6 *) &snh6, 0x0fff); + + + r = snprintf(buf2, sizeof(buf2), "%s %s{" DBQ(destination) " : " + DBQ(%s) ", " DBQ(prefix length) " : %d," + DBQ(next hop) " : " DBQ(%s) ", " DBQ(flags) + " : " DBQ(%s) ", " DBQ(metric) " : %d , " + DBQ(interface) " : " DBQ(%s) "}", + n ? "" : ", \"inet6 routes\" : [", n ? ", " : "" + , dst6out, prefix_len, nh6out, flags, metric + , iface); + + /* + r = snprintf(buf2, sizeof(buf2), "%s %s{" DBQ(destination) " : " + DBQ(%s) ", " DBQ(prefix length) " : %d," + DBQ(next hop) " : " DBQ(%s) ", " DBQ(flags) + " : " DBQ(%s) ", " DBQ(metric) " : %d , " + DBQ(interface) " : " DBQ(%s) "}", + n ? " " : '"inet6 routes" [' + , n ? ", " : "" + , dst6out, prefix_len, nh6out, flags, metric + , iface); + */ + + /* printf("%s\n", buf2); */ + + if(dst6out) { + free(dst6out); + dst6out=NULL; + } + if(nh6out) { + free(nh6out); + nh6out=NULL; + } + + if (fwrite(buf2, 1, r, out_file) != r) + { + report_err("error writing to '%s'", filename); + fclose(in_file); + fclose(out_file); + return 1; + } + n++; + } + if ( n > 0 ) { + r = snprintf(buf2, 2, "]"); + } + if (fwrite(buf2, 1, r, out_file) != r) + { + report_err("error writing to '%s'", filename); + fclose(in_file); + fclose(out_file); + return 1; + } + + + if (ferror(in_file)) + { + report_err("error reading from '%s'", IPV6_ROUTE_FILE); + fclose(in_file); + fclose(out_file); + return 1; + } + fclose(in_file); + + /* Now check if the new file is different from the cache one */ + fclose(out_file); + cache_file= fopen(cache_name, "r"); + if (cache_file == NULL) + { + /* Assume that any kind of error here calls for reporting */ + *need_report= 1; + } + + if (cache_file) + { + in_file= fopen(filename, "r"); + if (in_file == NULL) + { + report_err("unable to open '%s'", filename); + fclose(cache_file); + return 1; + } + + /* Compare them */ + while (r= fread(buf1, 1, sizeof(buf1), cache_file), r > 0) + { + if (fread(buf2, 1, sizeof(buf2), in_file) != r) + { + /* Ignore errors, just report */ + *need_report= 1; + break; + } + + if (memcmp(buf1, buf2, r) != 0) + { + /* Something changed, report */ + *need_report= 1; + break; + } + } + + /* Maybe something got added */ + if (!*need_report) + { + if (fread(buf2, 1, sizeof(buf2), in_file) != 0) + { + *need_report= 1; + } + } + fclose(cache_file); + fclose(in_file); + } + + if (*need_report) + { + if (rename(filename, cache_name) == -1) + { + report_err("renaming '%s' to '%s' failed", + filename, cache_name); + return 1; + } + } + else + { + if (unlink(filename) == -1) + { + report_err("unlinking '%s' failed", + filename); + } + } + + return 0; +} + + +static int rpt_ipv6(char *cache_name, char *out_name, char *opt_atlas, int opt_append) +{ + FILE *file; + FILE *fh; + char *cp; + char buf[256]; + struct timeval now; + + file= fopen(cache_name, "r"); + if (!file) + { + report_err("unable to open cache file '%s'", cache_name); + return 1; + } + + if (out_name) { + if(opt_append) + fh= fopen(out_name, "w"); + else + fh= fopen(out_name, "w"); + + if (!fh) + crondlog(DIE9 "unable to append to '%s'", out_name); + } + else + fh = stdout; + + fprintf(fh, "RESULT { "); + if(opt_atlas) + { + JS(id, opt_atlas); + } + gettimeofday(&now, NULL); + JS1(time, %ld, now.tv_sec); + + /* Copy all lines */ + while (fgets(buf, sizeof(buf), file) != NULL) + { + fputs(buf, fh); + } + fprintf(fh, "}\n"); + fclose(file); + fclose(fh); + + return 0; +} + +static void report(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + + fprintf(stderr, "rptaddr6: "); + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); + + va_end(ap); +} + +static void report_err(const char *fmt, ...) +{ + int t_errno; + va_list ap; + + t_errno= errno; + + va_start(ap, fmt); + + fprintf(stderr, "rptaddr6: "); + vfprintf(stderr, fmt, ap); + fprintf(stderr, ": %s\n", strerror(t_errno)); + + va_end(ap); +} diff --git a/networking/rptra6.c b/networking/rptra6.c index b481252..8b45e72 100644 --- a/networking/rptra6.c +++ b/networking/rptra6.c @@ -35,7 +35,7 @@ static void usage(void) exit(1); } -int rptra6_main(int argc, char *argv[]) MAIN_EXTERNALLY_VISIBLE; +int rptaddr6_main(int argc, char *argv[]) MAIN_EXTERNALLY_VISIBLE; int rptra6_main(int argc, char *argv[]) { int i, r, first, sock, on, nrecv, rcvd_ttl, olen; |