aboutsummaryrefslogtreecommitdiff
path: root/networking
diff options
context:
space:
mode:
Diffstat (limited to 'networking')
-rw-r--r--networking/rptaddrs.c5
-rw-r--r--networking/rptra6.c82
-rw-r--r--networking/rxtxrpt.c124
3 files changed, 200 insertions, 11 deletions
diff --git a/networking/rptaddrs.c b/networking/rptaddrs.c
index 8506ac8..5ec0d9f 100644
--- a/networking/rptaddrs.c
+++ b/networking/rptaddrs.c
@@ -549,11 +549,11 @@ static int setup_ipv6_rpt(FILE *of)
static int setup_dns(FILE *of)
{
int i, resolv_max;
- char nslist[MAXNS][INET6_ADDRSTRLEN * 2];
+ char *nslist[MAXNS];
resolv_max= 0;
- get_local_resolvers_nocache(nslist, &resolv_max);
+ get_local_resolvers(nslist, &resolv_max, NULL);
fprintf(of, ", " DBQ(dns) ": [ ");
for (i= 0; i<resolv_max; i++)
@@ -561,6 +561,7 @@ static int setup_dns(FILE *of)
fprintf(of, "%s{ " DBQ(nameserver) ": " DBQ(%s) " }",
i == 0 ? "" : ", ",
nslist[i]);
+ free(nslist[i]); nslist[i]= NULL;
}
fprintf(of, " ]");
diff --git a/networking/rptra6.c b/networking/rptra6.c
index c015134..7966e33 100644
--- a/networking/rptra6.c
+++ b/networking/rptra6.c
@@ -8,10 +8,11 @@
#include <netinet/ip_icmp.h>
#include <netinet/icmp6.h>
-#define OPT_STRING "lP:r:"
+#define OPT_STRING "lsI:P:r:u:"
enum {
OPT_l = (1 << 0),
+ OPT_s = (1 << 1),
};
#define DBQ(str) "\"" #str "\""
@@ -27,6 +28,10 @@ struct in6_addr in6addr_all_nodes = IN6ADDR_ALL_NODES_INIT; /* ff02::1 */
#define RA_PREF_HIGH 0x08
#define RA_PREF_LOW 0x18
+/* RFC-4861 */
+#define MAX_RTR_SOLICITATIONS 3
+#define RTR_SOLICITATION_INTERVAL 4
+
struct opt_rdnss /* RDNSS option */
{
uint8_t nd_opt_rdnss_type;
@@ -35,6 +40,10 @@ struct opt_rdnss /* RDNSS option */
uint32_t nd_opt_rdnss_lifetime;
};
+static int solicit_retries;
+static int solicit_sock;
+static char *update_cmd;
+
static void usage(void)
{
fprintf(stderr, "Usage: rptra6 <new> <out>\n");
@@ -132,6 +141,8 @@ static void do_resolv(char *str_resolv, char *str_resolv_new,
}
fclose(f);
rename(str_resolv_new, str_resolv);
+ if (update_cmd)
+ system(update_cmd);
}
if (lifetime)
*dnsexpires= time(NULL) + lifetime;
@@ -390,29 +401,64 @@ static void log_ra(char *out_name, char *new_name,
exit(1);
}
+static int send_sol(int sock)
+{
+ struct icmp6_hdr pkt;
+ struct sockaddr_in6 sin6;
+
+ if (solicit_retries <= 0)
+ return 0; /* Done */
+ solicit_retries--;
+
+ pkt.icmp6_type= ND_ROUTER_SOLICIT;
+ pkt.icmp6_code= 0;
+ pkt.icmp6_data32[0]= 0;
+
+ memset(&sin6, '\0', sizeof(sin6));
+ inet_pton(AF_INET6, "FF02::2", &sin6.sin6_addr);
+ sin6.sin6_family= AF_INET6;
+
+ sendto(sock, &pkt, sizeof(pkt), 0, &sin6, sizeof(sin6));
+
+ alarm(RTR_SOLICITATION_INTERVAL);
+
+ return 0;
+}
+
+static void solicit_alarm(int sig UNUSED_PARAM)
+{
+ send_sol(solicit_sock);
+}
+
int rptra6_main(int argc, char *argv[]) MAIN_EXTERNALLY_VISIBLE;
int rptra6_main(int argc, char *argv[])
{
- int i, sock, on, nrecv, do_log;
+ int i, sock, hlim, on, nrecv, do_log, do_solicit;
unsigned opts;
size_t len;
time_t dnsexpires;
- char *new_name, *out_name, *str_resolv, *str_resolv_new;
+ char *new_name, *out_name,
+ *str_interface, *str_resolv, *str_resolv_new, *str_update;
struct icmp6_hdr * icmp;
FILE *of;
char *str_pidfile;
struct sockaddr_in6 remote; /* responding internet address */
struct msghdr msg;
+ struct sigaction sa;
struct iovec iov[1];
char dnscurr[N_DNS][INET6_ADDRSTRLEN];
char cmsgbuf[256];
char packet[4096];
+ str_interface= NULL;
str_pidfile= NULL;
str_resolv= NULL;
- opts= getopt32(argv, OPT_STRING, &str_pidfile, &str_resolv);
+ str_update= NULL;
+ opts= getopt32(argv, OPT_STRING, &str_interface, &str_pidfile,
+ &str_resolv, &str_update);
do_log= !!(opts & OPT_l);
+ do_solicit= !!(opts & OPT_s);
if (do_log)
{
@@ -440,6 +486,8 @@ int rptra6_main(int argc, char *argv[])
}
}
+ update_cmd= str_update;
+
str_resolv_new= NULL;
if (str_resolv)
{
@@ -457,12 +505,35 @@ int rptra6_main(int argc, char *argv[])
return 1;
}
+ if (str_interface)
+ {
+ if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE,
+ str_interface, strlen(str_interface)+1) == -1)
+ {
+ close(sock);
+ return 1;
+ }
+ }
+
on = 1;
setsockopt(sock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, sizeof(on));
on = 1;
setsockopt(sock, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &on, sizeof(on));
+ if (do_solicit)
+ {
+ hlim= 255;
+ setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
+ &hlim, sizeof(hlim));
+ solicit_sock= sock;
+ solicit_retries= MAX_RTR_SOLICITATIONS;
+ sa.sa_handler= solicit_alarm;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags= 0;
+ sigaction(SIGALRM, &sa, NULL);
+ send_sol(sock);
+ }
icmp = (struct icmp6_hdr *) packet;
@@ -489,6 +560,8 @@ int rptra6_main(int argc, char *argv[])
nrecv= recvmsg(sock, &msg, 0);
if (nrecv < 0)
{
+ if (errno == EINTR)
+ continue;
printf("recvmsg failed: %s\n", strerror(errno));
break;
}
@@ -503,6 +576,7 @@ int rptra6_main(int argc, char *argv[])
case ICMP6_TIME_EXCEEDED: /* 3 */
case ICMP6_ECHO_REQUEST: /* 128 */
case ICMP6_ECHO_REPLY: /* 129 */
+ case MLD_LISTENER_QUERY: /* 130 */
case ND_NEIGHBOR_SOLICIT: /* 135 */
case ND_NEIGHBOR_ADVERT: /* 136 */
case ND_REDIRECT: /* 137 */
diff --git a/networking/rxtxrpt.c b/networking/rxtxrpt.c
index 609cedb..98e94f7 100644
--- a/networking/rxtxrpt.c
+++ b/networking/rxtxrpt.c
@@ -12,11 +12,15 @@ table if it has changed.
#include "libbb.h"
+#define NEW_FORMAT
+
#define DEV_FILE "/proc/net/dev"
#define IF_INET6_FILE "/proc/net/if_inet6"
#define IPV6_ROUTE_FILE "/proc/net/ipv6_route"
#define SUFFIX ".new"
+#define DBQ(str) "\"" #str "\""
+
int do_atlas= 0;
static int rpt_rxtx(void);
@@ -28,12 +32,11 @@ static void report_err(const char *fmt, ...);
int rxtxrpt_main(int argc, char *argv[])
{
int r, need_report;
- unsigned opt;
char *opt_atlas, *cache_name;
opt_atlas= NULL;
opt_complementary= NULL;
- opt= getopt32(argv, "A:", &opt_atlas);
+ getopt32(argv, "A:", &opt_atlas);
do_atlas= (opt_atlas != NULL);
@@ -46,13 +49,31 @@ int rxtxrpt_main(int argc, char *argv[])
if (do_atlas)
{
+#ifdef NEW_FORMAT
+ printf("RESULT { " DBQ(id) ": " DBQ(%s) ", ", opt_atlas);
+ printf(DBQ(fw) ": %d, ", get_atlas_fw_version());
+ printf(DBQ(time) ": %lld, ", (long long)time(NULL));
+ printf(DBQ(lts) ": %d, ", get_timesync());
+ printf(DBQ(interfaces) ": [");
+#else /* !NEW_FORMWAT */
printf("%s %lu ", opt_atlas, time(NULL));
+#endif /* NEW_FORMWAT */
}
r= rpt_rxtx();
if (r != 0)
return r;
+ if (do_atlas)
+ {
+#ifdef NEW_FORMAT
+ printf(" ] }\n");
+#else /* !NEW_FORMAT */
+ printf("\n");
+
+#endif /* NEW_FORMAT */
+ }
+
if (cache_name)
{
r= setup_ipv6_rpt(cache_name, &need_report);
@@ -66,12 +87,104 @@ int rxtxrpt_main(int argc, char *argv[])
}
}
- if (do_atlas)
- printf("\n");
-
return 0;
}
+#ifdef NEW_FORMAT
+static int rpt_rxtx(void)
+{
+ int i;
+ unsigned long long bytes_recv, pkt_recv, errors_recv, dropped_recv,
+ fifo_recv, framing_recv, compressed_recv, multicast_recv,
+ bytes_sent, pkt_sent, errors_sent, dropped_sent,
+ fifo_sent, collisions_sent, carr_lost_sent, compressed_sent;
+ char *cp, *infname;
+ FILE *file;
+ char buf[256];
+
+ file= fopen(DEV_FILE, "r");
+ if (!file)
+ {
+ report_err("unable to open '%s'", DEV_FILE);
+ return 1;
+ }
+
+ /* Skip two lines */
+ if (fgets(buf, sizeof(buf), file) == NULL ||
+ fgets(buf, sizeof(buf), file) == NULL)
+ {
+ report_err("unable to read from '%s'", DEV_FILE);
+ fclose(file);
+ return 1;
+ }
+
+ for (i= 0; i<4; i++)
+ {
+ if (fgets(buf, sizeof(buf), file) == NULL)
+ {
+ if (feof(file))
+ break;
+ report_err("unable to read from '%s'", DEV_FILE);
+ fclose(file);
+ return 1;
+ }
+
+ cp= buf;
+
+ /* Skip leading white space */
+ while (*cp == ' ')
+ cp++;
+ infname= cp;
+ cp= strchr(cp, ':');
+ if (cp == NULL)
+ {
+ report_err("format error in '%s'", DEV_FILE);
+ fclose(file);
+ return 1;
+ }
+
+ /* Get all the values */
+ if (sscanf(cp+1, "%llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu",
+ &bytes_recv, &pkt_recv, &errors_recv, &dropped_recv,
+ &fifo_recv, &framing_recv, &compressed_recv,
+ &multicast_recv,
+ &bytes_sent, &pkt_sent, &errors_sent, &dropped_sent,
+ &fifo_sent, &collisions_sent, &carr_lost_sent,
+ &compressed_sent) != 16)
+ {
+ report_err("format error in '%s'", DEV_FILE);
+ fclose(file);
+ return 1;
+ }
+
+ *cp= '\0';
+
+ printf("%s { " DBQ(name) ": " DBQ(%s) ", ",
+ i == 0 ? "" : ",", infname);
+
+ printf(DBQ(bytes_recv) ": %llu, ", bytes_recv);
+ printf(DBQ(pkt_recv) ": %llu, ", pkt_recv);
+ printf(DBQ(errors_recv) ": %llu, ", errors_recv);
+ printf(DBQ(dropped_recv) ": %llu, ", dropped_recv);
+ printf(DBQ(fifo_recv) ": %llu, ", fifo_recv);
+ printf(DBQ(framing_recv) ": %llu, ", framing_recv);
+ printf(DBQ(compressed_recv) ": %llu, ", compressed_recv);
+ printf(DBQ(multicast_recv) ": %llu, ", multicast_recv);
+ printf(DBQ(bytes_sent) ": %llu, ", bytes_sent);
+ printf(DBQ(pkt_sent) ": %llu, ", pkt_sent);
+ printf(DBQ(errors_sent) ": %llu, ", errors_sent);
+ printf(DBQ(dropped_sent) ": %llu, ", dropped_sent);
+ printf(DBQ(fifo_sent) ": %llu, ", fifo_sent);
+ printf(DBQ(collisions_sent) ": %llu, ", collisions_sent);
+ printf(DBQ(carr_lost_sent) ": %llu, ", carr_lost_sent);
+ printf(DBQ(compressed_sent) ": %llu", compressed_sent);
+ printf(" }");
+ }
+ fclose(file);
+
+ return 0;
+}
+#else /* !NEW_FORMAT */
static int rpt_rxtx(void)
{
int i;
@@ -120,6 +233,7 @@ static int rpt_rxtx(void)
return 0;
}
+#endif /* NEW_FORMAT */
static int setup_ipv6_rpt(char *cache_name, int *need_report)
{