diff options
Diffstat (limited to 'networking')
-rw-r--r-- | networking/rptaddrs.c | 5 | ||||
-rw-r--r-- | networking/rptra6.c | 82 | ||||
-rw-r--r-- | networking/rxtxrpt.c | 124 |
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) { |