aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBjørn Mork <bjorn@mork.no>2017-03-04 21:05:37 +0100
committerBjørn Mork <bjorn@mork.no>2017-03-04 21:05:37 +0100
commit8712f3f01a5acaa5426c03fc4510f18985b84b66 (patch)
tree6753dca376d4520648f31fa448cbab4561756d49
parent6937c3f2bd8cf40ce8d2f0d3fea37f076e4ce709 (diff)
ripe-atlas-fw: imported version 47504750
Signed-off-by: Bjørn Mork <bjorn@mork.no>
-rw-r--r--eperd/eooqd.c82
-rw-r--r--eperd/eperd.c60
-rw-r--r--eperd/evtdig.c53
-rw-r--r--eperd/evtraceroute.c1
-rw-r--r--eperd/ntp.c12
-rw-r--r--eperd/readresolv.c116
-rw-r--r--eperd/readresolv.h4
-rw-r--r--eperd/traceroute.c17
-rw-r--r--libevent-2.0.20-stable/evdns.c34
-rw-r--r--libevent-2.0.20-stable/include/event2/dns.h8
-rw-r--r--miscutils/ooqd.c22
-rw-r--r--networking/rptaddrs.c5
-rw-r--r--networking/rptra6.c82
-rw-r--r--networking/rxtxrpt.c124
-rw-r--r--shell/hush.c87
15 files changed, 563 insertions, 144 deletions
diff --git a/eperd/eooqd.c b/eperd/eooqd.c
index ed8ea64..8c11f62 100644
--- a/eperd/eooqd.c
+++ b/eperd/eooqd.c
@@ -28,6 +28,9 @@
#define BARRIER_CMD "barrier"
#define POST_CMD "post"
+#define RELOAD_RESOLV_CONF_CMD "reload_resolv_conf"
+
+#define RESOLV_CONF "/etc/resolv.conf"
struct slot
{
@@ -68,6 +71,9 @@ static struct builtin
static const char *atlas_id;
static const char *queue_id;
+static char *resolv_conf;
+static char output_filename[80];
+
static void report(const char *fmt, ...);
static void report_err(const char *fmt, ...);
@@ -88,18 +94,22 @@ int eooqd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int eooqd_main(int argc, char *argv[])
{
int r;
- char *pid_file_name, *instance_id_str;
+ size_t len;
+ char *pid_file_name, *interface_name, *instance_id_str;
char *check;
struct event *checkQueueEvent, *rePostEvent;
struct timeval tv;
struct rlimit limit;
+ struct stat sb;
atlas_id= NULL;
+ interface_name= NULL;
instance_id_str= NULL;
pid_file_name= NULL;
queue_id= "";
- (void)getopt32(argv, "A:i:P:q:", &atlas_id, &instance_id_str,
+ (void)getopt32(argv, "A:I:i:P:q:", &atlas_id,
+ &interface_name, &instance_id_str,
&pid_file_name, &queue_id);
if (argc != optind+1)
@@ -120,6 +130,28 @@ int eooqd_main(int argc, char *argv[])
}
}
+ if (interface_name)
+ {
+ len= strlen(RESOLV_CONF) + 1 +
+ strlen(interface_name) + 1;
+ resolv_conf= malloc(len);
+ snprintf(resolv_conf, len, "%s.%s",
+ RESOLV_CONF, interface_name);
+
+ /* Check if this resolv.conf exists. If it doen't, switch
+ * to the standard one.
+ */
+ if (stat(resolv_conf, &sb) == -1)
+ {
+ free(resolv_conf);
+ resolv_conf= strdup(RESOLV_CONF);
+ }
+ }
+ else
+ {
+ resolv_conf= strdup(RESOLV_CONF);
+ }
+
if(pid_file_name)
{
write_pidfile(pid_file_name);
@@ -145,6 +177,9 @@ int eooqd_main(int argc, char *argv[])
sizeof(state->curr_qfile));
strlcat(state->curr_qfile, SUFFIX, sizeof(state->curr_qfile));
+ snprintf(output_filename, sizeof(output_filename),
+ OOQD_OUT_PREFIX "%s/ooq.out", queue_id);
+
signal(SIGQUIT, SIG_DFL);
limit.rlim_cur= RLIM_INFINITY;
limit.rlim_max= RLIM_INFINITY;
@@ -156,13 +191,32 @@ int eooqd_main(int argc, char *argv[])
{
crondlog(DIE9 "event_base_new failed"); /* exits */
}
- DnsBase= evdns_base_new(EventBase, 1 /*initialize*/);
+ DnsBase= evdns_base_new(EventBase, 0 /*initialize*/);
if (!DnsBase)
{
event_base_free(EventBase);
crondlog(DIE9 "evdns_base_new failed"); /* exits */
}
+ if (interface_name)
+ {
+ r= evdns_base_set_interface(DnsBase, interface_name);
+ if (r == -1)
+ {
+ event_base_free(EventBase);
+ crondlog(DIE9 "evdns_base_set_interface failed");
+ /* exits */
+ }
+ }
+
+ r = evdns_base_resolv_conf_parse(DnsBase, DNS_OPTIONS_ALL,
+ resolv_conf);
+ if (r == -1)
+ {
+ event_base_free(EventBase);
+ crondlog(DIE9 "evdns_base_resolv_conf_parse failed"); /* exits */
+ }
+
checkQueueEvent= event_new(EventBase, -1, EV_TIMEOUT|EV_PERSIST,
checkQueue, NULL);
if (!checkQueueEvent)
@@ -190,7 +244,6 @@ static void checkQueue(evutil_socket_t fd UNUSED_PARAM,
{
int r;
struct stat sb;
- char filename[80];
if (!state->curr_file)
{
@@ -246,9 +299,7 @@ static void checkQueue(evutil_socket_t fd UNUSED_PARAM,
break; /* Wait for barrier to complete */
}
- snprintf(filename, sizeof(filename),
- OOQD_OUT_PREFIX "%s/ooq.out", queue_id);
- check_resolv_conf2(filename, atlas_id);
+ check_resolv_conf2(output_filename, atlas_id);
}
static int add_line(void)
@@ -328,6 +379,14 @@ static int add_line(void)
return 0;
}
+ /* Check for the reload resolv.conf command */
+ if (strcmp(cmdline, RELOAD_RESOLV_CONF_CMD) == 0)
+ {
+ /* Trigger a reload */
+ check_resolv_conf2(output_filename, atlas_id);
+ return 0; /* Done */
+ }
+
cmdstate= NULL;
reason= NULL;
for (bp= builtin_cmds; bp->cmd != NULL; bp++)
@@ -555,7 +614,6 @@ static void cmddone(void *cmdstate)
}
}
-#define RESOLV_CONF "/etc/resolv.conf"
static void check_resolv_conf2(const char *out_file, const char *atlasid)
{
static time_t last_time= -1;
@@ -564,7 +622,7 @@ static void check_resolv_conf2(const char *out_file, const char *atlasid)
FILE *fn;
struct stat sb;
- r= stat(RESOLV_CONF, &sb);
+ r= stat(resolv_conf, &sb);
if (r == -1)
{
crondlog(LVL8 "error accessing resolv.conf: %s",
@@ -573,10 +631,14 @@ static void check_resolv_conf2(const char *out_file, const char *atlasid)
}
if (sb.st_mtime == last_time)
+ {
+ crondlog(LVL7 "check_resolv_conf2: no change (time %d)",
+ sb.st_mtime);
return; /* resolv.conf did not change */
+ }
evdns_base_clear_nameservers_and_suspend(DnsBase);
r= evdns_base_resolv_conf_parse(DnsBase, DNS_OPTIONS_ALL,
- RESOLV_CONF);
+ resolv_conf);
evdns_base_resume(DnsBase);
if ((r != 0 || last_time != -1) && out_file != NULL)
diff --git a/eperd/eperd.c b/eperd/eperd.c
index 9c602c6..83aff15 100644
--- a/eperd/eperd.c
+++ b/eperd/eperd.c
@@ -57,6 +57,8 @@
#define URANDOM_DEV "/dev/urandom"
#define ATLAS_FW_VERSION "/home/atlas/state/FIRMWARE_APPS_VERSION"
+#define RESOLV_CONF "/etc/resolv.conf"
+
struct CronLine {
struct CronLine *cl_Next;
char *cl_Shell; /* shell command */
@@ -121,6 +123,7 @@ struct globals G;
static int do_kick_watchdog;
static char *out_filename= NULL;
static char *atlas_id= NULL;
+static char *resolv_conf;
static void CheckUpdates(evutil_socket_t fd, short what, void *arg);
static void CheckUpdatesHour(evutil_socket_t fd, short what, void *arg);
@@ -257,11 +260,14 @@ int eperd_main(int argc UNUSED_PARAM, char **argv)
unsigned opt;
int r, fd;
unsigned seed;
+ size_t len;
struct event *updateEventMin, *updateEventHour;
struct timeval tv;
struct rlimit limit;
+ struct stat sb;
const char *PidFileName = NULL;
+ char *interface_name= NULL;
atexit(my_exit);
@@ -270,8 +276,9 @@ int eperd_main(int argc UNUSED_PARAM, char **argv)
/* "-b after -f is ignored", and so on for every pair a-b */
opt_complementary = "f-b:b-f:S-L:L-S" USE_FEATURE_PERD_D(":d-l")
":i+:l+:d+"; /* -i, -l and -d have numeric param */
- opt = getopt32(argv, "i:l:L:fc:A:DP:" USE_FEATURE_PERD_D("d:") "O:",
- &instance_id, &LogLevel, &LogFile, &CDir,
+ opt = getopt32(argv, "I:i:l:L:fc:A:DP:" USE_FEATURE_PERD_D("d:") "O:",
+ &interface_name, &instance_id, &LogLevel,
+ &LogFile, &CDir,
&atlas_id, &PidFileName
USE_FEATURE_PERD_D(,&LogLevel), &out_filename);
/* both -d N and -l N set the same variable: LogLevel */
@@ -294,6 +301,29 @@ int eperd_main(int argc UNUSED_PARAM, char **argv)
logmode = LOGMODE_SYSLOG;
}
+ if (interface_name)
+ {
+ len= strlen(RESOLV_CONF) + 1 +
+ strlen(interface_name) + 1;
+ resolv_conf= malloc(len);
+ snprintf(resolv_conf, len, "%s.%s",
+ RESOLV_CONF, interface_name);
+
+ /* Check if this resolv.conf exists. If it doen't, switch
+ * to the standard one.
+ */
+ if (stat(resolv_conf, &sb) == -1)
+ {
+ free(resolv_conf);
+ resolv_conf= strdup(RESOLV_CONF);
+ }
+ }
+ else
+ {
+ resolv_conf= strdup(RESOLV_CONF);
+ }
+
+
do_kick_watchdog= !!(opt & OPT_D);
xchdir(CDir);
@@ -312,12 +342,31 @@ int eperd_main(int argc UNUSED_PARAM, char **argv)
{
crondlog(DIE9 "event_base_new failed"); /* exits */
}
- DnsBase= evdns_base_new(EventBase, 1 /*initialize*/);
+ DnsBase= evdns_base_new(EventBase, 0 /*!initialize*/);
if (!DnsBase)
{
crondlog(DIE9 "evdns_base_new failed"); /* exits */
}
+ if (interface_name)
+ {
+ r= evdns_base_set_interface(DnsBase, interface_name);
+ if (r == -1)
+ {
+ event_base_free(EventBase);
+ crondlog(DIE9 "evdns_base_set_interface failed");
+ /* exits */
+ }
+ }
+
+ r = evdns_base_resolv_conf_parse(DnsBase, DNS_OPTIONS_ALL,
+ resolv_conf);
+ if (r == -1)
+ {
+ event_base_free(EventBase);
+ crondlog(DIE9 "evdns_base_resolv_conf_parse failed"); /* exits */
+ }
+
fd= open(URANDOM_DEV, O_RDONLY);
/* Best effort, just ignore errors */
@@ -591,7 +640,6 @@ static void SynchronizeFile(const char *fileName)
DeleteFile();
}
-#define RESOLV_CONF "/etc/resolv.conf"
static void check_resolv_conf(void)
{
static time_t last_time= -1;
@@ -600,7 +648,7 @@ static void check_resolv_conf(void)
FILE *fn;
struct stat sb;
- r= stat(RESOLV_CONF, &sb);
+ r= stat(resolv_conf, &sb);
if (r == -1)
{
crondlog(LVL8 "error accessing resolv.conf: %s",
@@ -612,7 +660,7 @@ static void check_resolv_conf(void)
return; /* resolv.conf did not change */
evdns_base_clear_nameservers_and_suspend(DnsBase);
r= evdns_base_resolv_conf_parse(DnsBase, DNS_OPTIONS_ALL,
- RESOLV_CONF);
+ resolv_conf);
evdns_base_resume(DnsBase);
if ((r != 0 || last_time != -1) && out_filename)
diff --git a/eperd/evtdig.c b/eperd/evtdig.c
index df223ff..c5879de 100644
--- a/eperd/evtdig.c
+++ b/eperd/evtdig.c
@@ -231,8 +231,6 @@ struct tdig_base {
struct query_state *qry_head;
struct event statsReportEvent;
- int resolv_max;
- char nslist[MAXNS][INET6_ADDRSTRLEN * 2];
counter_t sendfail; /* # of failed sendto() */
counter_t sentok; /* # of successful sendto() */
@@ -297,6 +295,10 @@ struct query_state {
char * server_name;
char *out_filename ;
+ /* Contents of resolv.conf during a measurement */
+ int resolv_max;
+ char *nslist[MAXNS];
+
/* For fuzzing */
char *response_out;
char *response_in;
@@ -1343,10 +1345,6 @@ static bool argProcess (int argc, char *argv[], struct query_state *qry )
{
if( qry->opt_resolv_conf) {
qry->resolv_i = 0;
- get_local_resolvers(tdig_base->nslist, &tdig_base->resolv_max);
- if(tdig_base->resolv_max ) {
- qry->server_name = strdup(tdig_base->nslist[qry->resolv_i]);
- }
}
else if (optind != argc-1) {
crondlog(LVL9 "ERROR no server IP address in input");
@@ -1911,7 +1909,6 @@ struct tdig_base * tdig_base_new(struct event_base *event_base)
tdig_base->recvbytes = 0;
tdig_base->timeout = 0;
tdig_base->activeqry = 0;
- tdig_base->resolv_max = 0;
memset(tdig_base, 0, sizeof(struct tdig_base));
tdig_base->event_base = event_base;
@@ -1970,17 +1967,20 @@ void tdig_start (void *arg)
/* Get time in case we don't send any packet */
qry->xmit_time= time(NULL);
qry->resolv_i = 0;
- crondlog(LVL5 "RESOLV QUERY FREE %s resolv_max %d", qry->server_name, tdig_base->resolv_max);
+ crondlog(LVL5 "RESOLV QUERY FREE %s resolv_max %d", qry->server_name, qry->resolv_max);
if( qry->opt_resolv_conf) {
- get_local_resolvers (tdig_base->nslist, &tdig_base->resolv_max);
- crondlog(LVL5 "AAA RESOLV QUERY FREE %s resolv_max %d %d", qry->server_name, tdig_base->resolv_max, qry->resolv_i);
- if(tdig_base->resolv_max ) {
+ get_local_resolvers (qry->nslist,
+ &qry->resolv_max,
+ qry->infname);
+ crondlog(LVL5 "AAA RESOLV QUERY FREE %s resolv_max %d %d", qry->server_name, qry->resolv_max, qry->resolv_i);
+ if(qry->resolv_max ) {
free(qry->server_name);
qry->server_name = NULL;
- qry->server_name = strdup(tdig_base->nslist[qry->resolv_i]);
+ qry->server_name = qry->nslist[qry->resolv_i];
+ qry->nslist[qry->resolv_i]= NULL;
}
else {
- crondlog(LVL5 "AAA RESOLV QUERY FREE %s resolv_max is zero %d i %d", qry->server_name, tdig_base->resolv_max, qry->resolv_i);
+ crondlog(LVL5 "AAA RESOLV QUERY FREE %s resolv_max is zero %d i %d", qry->server_name, qry->resolv_max, qry->resolv_i);
free(qry->server_name);
qry->server_name = NULL;
snprintf(line, DEFAULT_LINE_LENGTH, "\"nameserver\": \"no local resolvers found\"");
@@ -2201,6 +2201,7 @@ static void ChangetoDnsNameFormat(u_char * dns, char* qry)
static void free_qry_inst(struct query_state *qry)
{
+ int i;
struct timeval asap = { 1, 0 };
BLURT(LVL5 "freeing instance of %s ", qry->server_name);
@@ -2248,18 +2249,27 @@ static void free_qry_inst(struct query_state *qry)
if ( qry->opt_resolv_conf) {
// this loop goes over servers in /etc/resolv.conf
// select the next server and restart
- if(qry->resolv_i < tdig_base->resolv_max) {
+ if(qry->resolv_i < qry->resolv_max) {
if(qry->server_name) {
free (qry->server_name);
qry->server_name = NULL;
}
- qry->server_name = strdup(tdig_base->nslist[qry->resolv_i]);
+ qry->server_name = strdup(qry->nslist[qry->resolv_i]);
qry->qst = STATUS_NEXT_QUERY;
evtimer_add(&qry->next_qry_timer, &asap);
return;
}
}
+ for (i= 0; i<MAXNS; i++)
+ {
+ if (qry->nslist[i])
+ {
+ free(qry->nslist[i]);
+ qry->nslist[i]= NULL;
+ }
+ }
+
switch(qry->qst){
case STATUS_RETRANSMIT_QUERY:
break;
@@ -2281,6 +2291,7 @@ static void free_qry_inst(struct query_state *qry)
static int tdig_delete(void *state)
{
+ int i;
struct query_state *qry;
qry = state;
@@ -2343,6 +2354,14 @@ static int tdig_delete(void *state)
free(qry->server_name);
qry->server_name = NULL;
}
+ for (i= 0; i<MAXNS; i++)
+ {
+ if (qry->nslist[i])
+ {
+ free(qry->nslist[i]);
+ qry->nslist[i]= NULL;
+ }
+ }
if (qry->udp_fd != -1)
{
event_del(&qry->event);
@@ -2451,7 +2470,7 @@ void printReply(struct query_state *qry, int wire_size, unsigned char *result)
if ( qry->opt_resolv_conf ) {
JD (subid, (qry->resolv_i+1));
- JD (submax, qry->base->resolv_max);
+ JD (submax, qry->resolv_max);
}
if( qry->ressent && qry->server_name)
@@ -2655,7 +2674,7 @@ void printReply(struct query_state *qry, int wire_size, unsigned char *result)
if(qry->opt_resolv_conf){
qry->resolv_i++;
- if(qry->resolv_i >= tdig_base->resolv_max) {
+ if(qry->resolv_i >= qry->resolv_max) {
write_out = TRUE;
if(qry->opt_rset) {
AS ("]"); /* reseultset : [{}] */
diff --git a/eperd/evtraceroute.c b/eperd/evtraceroute.c
index d5e0d36..c596e3c 100644
--- a/eperd/evtraceroute.c
+++ b/eperd/evtraceroute.c
@@ -8,6 +8,7 @@
#include <syslog.h>
#include <event2/event.h>
#include <event2/event_struct.h>
+#include <event2/dns.h>
#include "eperd.h"
diff --git a/eperd/ntp.c b/eperd/ntp.c
index fb788c2..c1d509a 100644
--- a/eperd/ntp.c
+++ b/eperd/ntp.c
@@ -1830,12 +1830,11 @@ static void traceroute_start2(void *state)
ntpstate= state;
- if (ntpstate->busy)
+ if (!ntpstate->busy)
{
- printf("ntp_start: busy, can't start\n");
+ printf("ntp_start: not busy, can't continue\n");
return;
}
- ntpstate->busy= 1;
ntpstate->min= ULONG_MAX;
ntpstate->max= 0;
@@ -2070,6 +2069,13 @@ static void ntp_start(void *state)
ntpstate= state;
+ if (ntpstate->busy)
+ {
+ printf("ntp_start: busy, can't start\n");
+ return;
+ }
+ ntpstate->busy= 1;
+
if (ntpstate->response_out)
{
ntpstate->resp_file_out= fopen(ntpstate->response_out, "w");
diff --git a/eperd/readresolv.c b/eperd/readresolv.c
index 9d04866..df464bc 100644
--- a/eperd/readresolv.c
+++ b/eperd/readresolv.c
@@ -7,18 +7,15 @@
#include "libbb.h"
#include "resolv.h"
#include "eperd.h"
+#include "readresolv.h"
#include <math.h>
-static void nameserver_ip_add (char *nsentry, char *ip_as_string)
+static void nameserver_ip_add (char **nsentry, char *ip_as_string)
{
-
- strncpy (nsentry, ip_as_string, LINEL);
- // printf("AA added nameserver %s\n", ip_as_string);
- // printf("AA added nameserver to ns %s\n", nsentry);
- return;
+ *nsentry= strdup(ip_as_string);
}
-static int resolv_conf_parse_line (char *nsentry, char *line)
+static int resolv_conf_parse_line (char **nsentry, char *line)
{
#define NEXT_TOKEN strtok_r(NULL, delims, &strtok_state)
@@ -32,7 +29,7 @@ static int resolv_conf_parse_line (char *nsentry, char *line)
char *const nameserver = NEXT_TOKEN;
if (nameserver) {
if(nameserver[(strlen(nameserver) - 1)] == '\n')
- nameserver[(strlen(nameserver) - 1)] = NULL;
+ nameserver[(strlen(nameserver) - 1)] = '\0';
nameserver_ip_add(nsentry, nameserver);
//printf("AA added nameserver %s\n", nsentry);
return 1;
@@ -41,108 +38,51 @@ static int resolv_conf_parse_line (char *nsentry, char *line)
return 0;
}
-void get_local_resolvers(char nslist[MAXNS][INET6_ADDRSTRLEN * 2],
- int *resolv_max)
+void get_local_resolvers(char *nslist[MAXNS], int *resolv_max, char *ifname)
{
#ifndef RESOLV_CONF
#define RESOLV_CONF "/etc/resolv.conf"
#endif
char buf[LINEL];
+ char filename[80];
char *buf_start;
int i = 0;
- time_t now;
- int r;
struct stat sb;
+ FILE *R;
- static resolv_last_check = -1;
- static time_t last_time= -1;
-
- now = time(NULL);
-
- if(*resolv_max){
- if ( pow (resolv_last_check - now, 2) > 3) {
- crondlog(LVL5 "check the %s", RESOLV_CONF);
- }
- else {
- return;
- }
-
- }
-
-
- r = stat(RESOLV_CONF, &sb);
- if (r == -1)
- {
- crondlog(LVL8 "error accessing resolv.conf: %s",
- strerror(errno));
- return;
- }
-
- resolv_last_check = now;
-
- if (last_time == sb.st_mtime)
+ if (ifname)
{
- /* nothing changed */
- crondlog(LVL5 "re-read %s. not reading this time", RESOLV_CONF);
- return;
- }
- else {
- crondlog(LVL5 "re-read %s . it has changed", RESOLV_CONF);
- }
-
- FILE *R = fopen (RESOLV_CONF, "r");
- if (R != NULL) {
- while ( (fgets (buf, LINEL, R)) && (i < MAXNS)) {
- buf_start = buf;
- if(resolv_conf_parse_line(nslist[i], buf) ) {
- crondlog(LVL5 "parsed file %s , line %s i=%d", RESOLV_CONF, buf_start, i);
- i++;
- }
- else
- crondlog(LVL5 "ERROR failed to parse from %s i=%d, line %s", RESOLV_CONF, i, buf_start);
+ snprintf(filename, sizeof(filename), "%s.%s",
+ RESOLV_CONF, ifname);
+
+ /* Check if it exists */
+ if (stat(filename, &sb) == -1)
+ {
+ crondlog(LVL8 "get_local_resolvers: stat of %s failed: %s",
+ filename, strerror(errno));
+ /* Fall back to resolv.conf */
+ strlcpy(filename, RESOLV_CONF, sizeof(filename));
}
- fclose (R);
}
-
- last_time = sb.st_mtime;
-
- *resolv_max = i;
- return;
-}
-
-void get_local_resolvers_nocache(char nslist[MAXNS][INET6_ADDRSTRLEN * 2],
- int *resolv_max)
-{
-
-#ifndef RESOLV_CONF
-#define RESOLV_CONF "/etc/resolv.conf"
-#endif
- FILE *R;
- char buf[LINEL];
- char *buf_start;
- int i = 0;
- int r;
- struct stat sb;
-
- r = stat(RESOLV_CONF, &sb);
- if (r == -1)
+ else
{
- crondlog(LVL8 "error accessing resolv.conf: %s",
- strerror(errno));
- return;
+ /* Just use resolv.conf */
+ strlcpy(filename, RESOLV_CONF, sizeof(filename));
}
- R = fopen (RESOLV_CONF, "r");
+ crondlog(LVL8 "get_local_resolvers: using %s", filename);
+
+ R = fopen (filename, "r");
if (R != NULL) {
while ( (fgets (buf, LINEL, R)) && (i < MAXNS)) {
buf_start = buf;
- if(resolv_conf_parse_line(nslist[i], buf) ) {
- crondlog(LVL5 "parsed file %s , line %s i=%d", RESOLV_CONF, buf_start, i);
+ if(resolv_conf_parse_line(&nslist[i], buf) ) {
+ crondlog(LVL5 "parsed file %s , line %s i=%d", filename, buf_start, i);
i++;
}
else
- crondlog(LVL5 "ERROR failed to parse from %s i=%d, line %s", RESOLV_CONF, i, buf_start);
+ crondlog(LVL5 "ERROR failed to parse from %s i=%d, line %s", filename, i, buf_start);
}
fclose (R);
}
diff --git a/eperd/readresolv.h b/eperd/readresolv.h
index a71fd4a..2223a6d 100644
--- a/eperd/readresolv.h
+++ b/eperd/readresolv.h
@@ -2,6 +2,4 @@
* Copyright (c) 2013-2014 RIPE NCC <atlas@ripe.net>
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
*/
-void get_local_resolvers(char nslist[MAXNS][INET6_ADDRSTRLEN * 2], int *resolv_max);
-void get_local_resolvers_nocache(char nslist[MAXNS][INET6_ADDRSTRLEN * 2],
- int *resolv_max);
+void get_local_resolvers(char *nslist[MAXNS], int *resolv_max, char *infname);
diff --git a/eperd/traceroute.c b/eperd/traceroute.c
index 441aebd..b335a9d 100644
--- a/eperd/traceroute.c
+++ b/eperd/traceroute.c
@@ -3977,7 +3977,7 @@ for (i= 0; argv[i] != NULL; i++)
state->maxpacksize= maxpacksize;
state->maxhops= maxhops;
state->gaplimit= gaplimit;
- state->interface= interface;
+ state->interface= interface ? strdup(interface) : NULL;
state->destportstr= strdup(destportstr);
state->duptimeout= duptimeout*1000;
state->timeout= timeout*1000;
@@ -4057,9 +4057,9 @@ static void traceroute_start2(void *state)
trtstate= state;
- if (trtstate->busy)
+ if (!trtstate->busy)
{
- printf("traceroute_start: busy, can't start\n");
+ printf("traceroute_start: not busy, can't continue\n");
return;
}
trtstate->busy= 1;
@@ -4180,6 +4180,8 @@ static int create_socket(struct trtstate *state, int do_tcp)
if (bind_interface(state->socket_icmp,
af, state->interface) == -1)
{
+ crondlog(LVL7 "binding to interface '%s' failed with '%s'", state->interface, strerror(errno));
+
snprintf(line, sizeof(line),
", " DBQ(error) ":" DBQ(bind_interface failed) " }");
add_str(state, line);
@@ -4443,6 +4445,13 @@ static void traceroute_start(void *state)
trtstate= state;
+ if (trtstate->busy)
+ {
+ printf("traceroute_start: busy, can't start\n");
+ return;
+ }
+ trtstate->busy= 1;
+
if (trtstate->response_out)
{
trtstate->resp_file_out= fopen(trtstate->response_out, "w");
@@ -4493,6 +4502,8 @@ static int traceroute_delete(void *state)
free(trtstate->atlas);
trtstate->atlas= NULL;
+ free(trtstate->interface);
+ trtstate->interface= NULL;
free(trtstate->bundle_id);
trtstate->bundle_id= NULL;
free(trtstate->hostname);
diff --git a/libevent-2.0.20-stable/evdns.c b/libevent-2.0.20-stable/evdns.c
index cf38418..b9110f0 100644
--- a/libevent-2.0.20-stable/evdns.c
+++ b/libevent-2.0.20-stable/evdns.c
@@ -313,6 +313,8 @@ struct evdns_base {
struct event_base *event_base;
+ char *interface_name;
+
/* The number of good nameservers that we have */
int global_good_nameservers;
@@ -2475,6 +2477,16 @@ _evdns_nameserver_add_impl(struct evdns_base *base, const struct sockaddr *addre
ns->socket = socket(address->sa_family, SOCK_DGRAM, 0);
if (ns->socket < 0) { err = 1; goto out1; }
+ if (ns->base->interface_name)
+ {
+ if (setsockopt(ns->socket, SOL_SOCKET, SO_BINDTODEVICE,
+ ns->base->interface_name,
+ strlen(ns->base->interface_name)+1) == -1)
+ {
+ err= 2;
+ goto out2;
+ }
+ }
evutil_make_socket_closeonexec(ns->socket);
evutil_make_socket_nonblocking(ns->socket);
@@ -3967,6 +3979,12 @@ evdns_base_free_and_unlock(struct evdns_base *base, int fail_requests)
base->server_head = NULL;
base->global_good_nameservers = 0;
+ if (base->interface_name)
+ {
+ free(base->interface_name);
+ base->interface_name= NULL;
+ }
+
if (base->global_search_state) {
for (dom = base->global_search_state->head; dom; dom = dom_next) {
dom_next = dom->next;
@@ -3999,6 +4017,22 @@ evdns_base_free(struct evdns_base *base, int fail_requests)
evdns_base_free_and_unlock(base, fail_requests);
}
+int evdns_base_set_interface(struct evdns_base *base, char *interface_name)
+{
+ if (base->interface_name)
+ {
+ free(base->interface_name);
+ base->interface_name= NULL;
+ }
+ if (!interface_name)
+ return 0;
+
+ base->interface_name= strdup(interface_name);
+ if (!base->interface_name)
+ return -1;
+ return 0;
+}
+
void
evdns_shutdown(int fail_requests)
{
diff --git a/libevent-2.0.20-stable/include/event2/dns.h b/libevent-2.0.20-stable/include/event2/dns.h
index ca0da3c..797d3f9 100644
--- a/libevent-2.0.20-stable/include/event2/dns.h
+++ b/libevent-2.0.20-stable/include/event2/dns.h
@@ -231,6 +231,14 @@ struct evdns_base * evdns_base_new(struct event_base *event_base, int initialize
void evdns_base_free(struct evdns_base *base, int fail_requests);
/**
+ Set the outging interface to be used for DNS queries
+
+ @param base the evdns base to modify
+ @param interface_name the name of the interface to be used
+ */
+int evdns_base_set_interface(struct evdns_base *base, char *interface_name);
+
+/**
Convert a DNS error code to a string.
@param err the DNS error code
diff --git a/miscutils/ooqd.c b/miscutils/ooqd.c
index 85114c9..44721e9 100644
--- a/miscutils/ooqd.c
+++ b/miscutils/ooqd.c
@@ -116,9 +116,9 @@ static void skip_nonspace(char *cp, char **ncpp)
*ncpp= cp;
}
-static void find_eos(char *cp, char **ncpp)
+static void find_eos(char *cp, char **ncpp, char quote_char)
{
- while (cp[0] != '\0' && cp[0] != '"')
+ while (cp[0] != '\0' && cp[0] != quote_char)
cp++;
*ncpp= cp;
}
@@ -250,7 +250,7 @@ printf("got cp %p, line %p, '%s'\n", cp, line, cp);
if (cp[0] == '"')
{
/* Special code for strings */
- find_eos(cp+1, &ncp);
+ find_eos(cp+1, &ncp, '"');
if (ncp[0] != '"')
{
report(
@@ -263,6 +263,22 @@ printf("got cp %p, line %p, '%s'\n", cp, line, cp);
cp[0]= '\0';
cp++;
}
+ else if (cp[0] == '\'')
+ {
+ /* Also try single quotes */
+ find_eos(cp+1, &ncp, '\'');
+ if (ncp[0] != '\'')
+ {
+ report(
+ "command line '%s', end of string not found",
+ line);
+ continue; /* Just skip it */
+ }
+ argv[argc]= cp+1;
+ cp= ncp;
+ cp[0]= '\0';
+ cp++;
+ }
else
{
skip_nonspace(cp, &ncp);
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)
{
diff --git a/shell/hush.c b/shell/hush.c
index 54d0c55..d696d73 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -102,6 +102,7 @@
/* In progress... */
#define ENABLE_HUSH_FUNCTIONS 0
+#define DBQ(str) "\"" #str "\""
/* If you comment out one of these below, it will be #defined later
* to perform debug printfs to stderr: */
@@ -772,6 +773,7 @@ static int builtin_dfrm(char **argv);
static int builtin_rxtxrpt(char **argv);
static int builtin_rptaddrs(char **argv);
static int builtin_rptuptime(char **argv);
+static int builtin_onlyuptime(char **argv);
static int builtin_true(char **argv);
static int builtin_set(char **argv);
static int builtin_shift(char **argv);
@@ -833,6 +835,7 @@ static const struct built_in_command bltins[] = {
BLTIN("rxtxrpt" , builtin_rxtxrpt, "report RX and TX"),
BLTIN("rptaddrs" , builtin_rptaddrs, "report address(es), route(s), and dns"),
BLTIN("rptuptime" , builtin_rptuptime, "report uptime"),
+ BLTIN("onlyuptime" , builtin_onlyuptime, "report uptime in seconds"),
BLTIN("echo" , builtin_echo, "Write to stdout"),
BLTIN("eval" , builtin_eval, "Construct and run shell command"),
BLTIN("exec" , builtin_exec, "Execute command, don't return to shell"),
@@ -4536,6 +4539,79 @@ static int builtin_epoch (char **argv)
return EXIT_SUCCESS;
}
+#define NEW_FORMAT
+
+#ifdef NEW_FORMAT
+static int builtin_buddyinfo(char **argv)
+{
+ char *lowmemChar;
+ unsigned lowmem = 0;
+ FILE *fp = xfopen_for_read("/proc/buddyinfo");
+ char aa[10];
+ char *my_mac ;
+ int i = 0;
+ int j = 0;
+ int memBlock = 4;
+ int need_reboot = 0; // don't reboot
+ int freeMem = 0;
+ int jMax = 64; // enough
+ struct sysinfo info;
+
+ lowmemChar = argv[1];
+
+ if(lowmemChar)
+ lowmem = xatou(lowmemChar);
+ fscanf(fp, "%s", aa);
+ fscanf(fp, "%s", aa);
+ fscanf(fp, "%s", aa);
+ fscanf(fp, "%s", aa);
+
+ my_mac = getenv("ETHER_SCANNED");
+
+ if (lowmem >= 4 )
+ {
+ /* We need to reboot unless we find a big enough chunk
+ * of memory.
+ */
+ need_reboot = 1;
+ }
+ printf ("RESULT { " DBQ(id) ": " DBQ(9001) ", " DBQ(time) ": %lld",
+ (long long)time(0));
+ if (my_mac != NULL)
+ printf(", " DBQ(macaddr) ": " DBQ(%s), my_mac);
+
+ /* get uptime and print it */
+ sysinfo(&info);
+ printf (", " DBQ(uptime) ": %ld", info.uptime );
+
+ printf(", " DBQ(buddyinfo) ": [ ");
+ for (j=0; j < jMax; j++)
+ {
+ if (fscanf(fp, "%d", &i) != 1)
+ break;
+ printf("%s%d", j == 0 ? "" : ", ", i);
+ freeMem += ( memBlock * i);
+ if (i > 0 && lowmem >= 4 && memBlock >= lowmem)
+ {
+ /* Found a big enough chunk */
+ need_reboot = 0;
+ }
+ memBlock *= 2;
+ }
+
+ /* now print it */
+ printf (" ], " DBQ(freemem) ": %d }\n" , freeMem);
+
+ fclose (fp);
+
+ if(need_reboot)
+ {
+ fprintf(stderr, "buddy info returned 1 for block %d\n", lowmem);
+ return (EXIT_FAILURE);
+ }
+ return 0;
+}
+#else /* !NEW_FORMAT */
static int builtin_buddyinfo(char **argv)
{
char *lowmemChar;
@@ -4625,6 +4701,7 @@ static int builtin_buddyinfo(char **argv)
}
return 0;
}
+#endif /* NEW_FORMAT */
static int builtin_findpid(char **argv)
{
@@ -4710,6 +4787,16 @@ static int builtin_rptuptime(char **argv __attribute((unused)))
return 0;
}
+static int builtin_onlyuptime(char **argv __attribute((unused)))
+{
+ struct sysinfo info;
+
+ sysinfo(&info);
+ printf("%ld\n", (long)info.uptime);
+
+ return 0;
+}
+
static int builtin_rchoose(char **argv)
{
int argc = 0;