DEFEND
};
-#define DBG(fmt,args...) \
+#define VDBG(fmt,args...) \
do { } while (0)
-#define VDBG DBG
static unsigned long opts;
#define FOREGROUND (opts & 1)
*/
static void pick(struct in_addr *ip)
{
- unsigned tmp;
+ unsigned tmp;
/* use cheaper math than lrand48() mod N */
do {
ip->s_addr = htonl((LINKLOCAL_ADDR + 0x0100) + tmp);
}
+/* TODO: we need a flag to direct bb_[p]error_msg output to stderr. */
+
/**
* Broadcast an ARP packet.
*/
-static int arp(int fd, struct sockaddr *saddr, int op,
+static void arp(int fd, struct sockaddr *saddr, int op,
const struct ether_addr *source_addr, struct in_addr source_ip,
const struct ether_addr *target_addr, struct in_addr target_ip)
{
// send it
if (sendto(fd, &p, sizeof (p), 0, saddr, sizeof (*saddr)) < 0) {
- if (FOREGROUND)
- perror("sendto");
- else
- syslog(LOG_ERR, "sendto: %s", strerror(errno));
- return -errno;
+ bb_perror_msg("sendto");
+ //return -errno;
}
- return 0;
+ // Currently all callers ignore errors, that's why returns are
+ // commented out...
+ //return 0;
}
/**
* Run a script.
- * TODO: we need a flag to direct bb_[p]error_msg output to stderr.
*/
static int run(char *script, char *arg, char *intf, struct in_addr *ip)
{
if (ip != NULL) {
char *addr = inet_ntoa(*ip);
setenv("ip", addr, 1);
- if (!FOREGROUND)
- syslog(LOG_INFO, "%s %s %s", arg, intf, addr);
+ bb_info_msg("%s %s %s", arg, intf, addr);
}
pid = vfork();
goto bad;
} else if (pid == 0) { // child
execl(script, script, arg, NULL);
- if (FOREGROUND)
- perror("execl");
- else
- syslog(LOG_ERR, "execl: %s", strerror(errno));
+ bb_perror_msg("execl");
_exit(EXIT_FAILURE);
}
goto bad;
}
if (WEXITSTATUS(status) != 0) {
- if (FOREGROUND)
- bb_error_msg("script %s failed, exit=%d\n",
- script, WEXITSTATUS(status));
- else
- syslog(LOG_ERR, "script %s failed, exit=%d",
- script, WEXITSTATUS(status));
+ bb_error_msg("script %s failed, exit=%d",
+ script, WEXITSTATUS(status));
return -errno;
}
}
return 0;
bad:
status = -errno;
- if (FOREGROUND)
- bb_perror_msg("%s %s, %s",
- arg, intf, why);
- else
- syslog(LOG_ERR, "%s %s, %s: %s",
- arg, intf, why, strerror(errno));
+ bb_perror_msg("%s %s, %s", arg, intf, why);
return status;
}
// parse commandline: prog [options] ifname script
char *r_opt;
- bb_opt_complementally = "vv"; // -v options accumulate
+ bb_opt_complementally = "vv:vf"; // -v accumulates and implies -f
opts = bb_getopt_ulflags(argc, argv, "fqr:v", &r_opt, &verbose);
- if (opts & 4) {
+ if (!FOREGROUND) {
+ /* Do it early, before all bb_xx_msg calls */
+ logmode = LOGMODE_SYSLOG;
+ openlog(bb_applet_name, 0, LOG_DAEMON);
+ }
+ if (opts & 4) { // -r n.n.n.n
if (inet_aton(r_opt, &ip) == 0
|| (ntohl(ip.s_addr) & IN_CLASSB_NET) != LINKLOCAL_ADDR) {
bb_error_msg_and_die("invalid link address");
}
}
- if (verbose) opts |= 1;
argc -= optind;
argv += optind;
if (argc != 2)
bb_show_usage();
-
intf = argv[0];
script = argv[1];
setenv("interface", intf, 1);
- openlog(bb_applet_name, 0, LOG_DAEMON);
// initialize the interface (modprobe, ifup, etc)
if (run(script, "init", intf, NULL) < 0)
// daemonize now; don't delay system startup
if (!FOREGROUND) {
- xdaemon(0, verbose);
- syslog(LOG_INFO, "start, interface %s", intf);
+ setsid();
+ xdaemon(0, 0);
+ bb_info_msg("start, interface %s", intf);
}
// run the dynamic address negotiation protocol,
tv1.tv_sec++;
}
tv1.tv_sec += timeout / 1000;
-
+
VDBG("...wait %ld %s nprobes=%d, nclaims=%d\n",
timeout, intf, nprobes, nclaims);
switch (poll(fds, 1, timeout)) {
VDBG("state = %d\n", state);
switch (state) {
case PROBE:
- // timeouts in the PROBE state means no conflicting ARP packets
+ // timeouts in the PROBE state mean no conflicting ARP packets
// have been received, so we can progress through the states
if (nprobes < PROBE_NUM) {
nprobes++;
VDBG("probe/%d %s@%s\n",
nprobes, intf, inet_ntoa(ip));
- (void)arp(fd, &saddr, ARPOP_REQUEST,
+ arp(fd, &saddr, ARPOP_REQUEST,
ð_addr, null_ip,
&null_addr, ip);
timeout = PROBE_MIN * 1000;
nclaims = 0;
VDBG("announce/%d %s@%s\n",
nclaims, intf, inet_ntoa(ip));
- (void)arp(fd, &saddr, ARPOP_REQUEST,
+ arp(fd, &saddr, ARPOP_REQUEST,
ð_addr, ip,
ð_addr, ip);
timeout = ANNOUNCE_INTERVAL * 1000;
}
break;
case RATE_LIMIT_PROBE:
- // timeouts in the RATE_LIMIT_PROBE state means no conflicting ARP packets
+ // timeouts in the RATE_LIMIT_PROBE state mean no conflicting ARP packets
// have been received, so we can move immediately to the announce state
state = ANNOUNCE;
nclaims = 0;
VDBG("announce/%d %s@%s\n",
nclaims, intf, inet_ntoa(ip));
- (void)arp(fd, &saddr, ARPOP_REQUEST,
+ arp(fd, &saddr, ARPOP_REQUEST,
ð_addr, ip,
ð_addr, ip);
timeout = ANNOUNCE_INTERVAL * 1000;
break;
case ANNOUNCE:
- // timeouts in the ANNOUNCE state means no conflicting ARP packets
+ // timeouts in the ANNOUNCE state mean no conflicting ARP packets
// have been received, so we can progress through the states
if (nclaims < ANNOUNCE_NUM) {
nclaims++;
VDBG("announce/%d %s@%s\n",
nclaims, intf, inet_ntoa(ip));
- (void)arp(fd, &saddr, ARPOP_REQUEST,
+ arp(fd, &saddr, ARPOP_REQUEST,
ð_addr, ip,
ð_addr, ip);
timeout = ANNOUNCE_INTERVAL * 1000;
conflicts = 0;
timeout = -1; // Never timeout in the monitor state.
- // NOTE: all other exit paths
+ // NOTE: all other exit paths
// should deconfig ...
if (QUIT)
return EXIT_SUCCESS;
if (fds[0].revents & POLLERR) {
// FIXME: links routinely go down;
// this shouldn't necessarily exit.
- bb_error_msg("%s: poll error\n", intf);
+ bb_error_msg("%s: poll error", intf);
if (ready) {
run(script, "deconfig",
intf, &ip);
target_ip_conflict = 1;
}
- VDBG("state = %d, source ip conflict = %d, target ip conflict = %d\n",
+ VDBG("state = %d, source ip conflict = %d, target ip conflict = %d\n",
state, source_ip_conflict, target_ip_conflict);
switch (state) {
case PROBE:
VDBG("monitor conflict -- defending\n");
state = DEFEND;
timeout = DEFEND_INTERVAL * 1000;
- (void)arp(fd, &saddr,
+ arp(fd, &saddr,
ARPOP_REQUEST,
ð_addr, ip,
ð_addr, ip);
} // switch poll
}
bad:
- if (FOREGROUND)
- perror(why);
- else
- syslog(LOG_ERR, "%s %s, %s error: %s",
- bb_applet_name, intf, why, strerror(errno));
+ bb_perror_msg("%s, %s", intf, why);
return EXIT_FAILURE;
}