[BusyBox] Re: [patch] zcip for busybox (rfc3927)
Tito
farmatito at tiscali.it
Tue Apr 19 19:10:05 UTC 2005
Hi,
this is a first attempt of size optimization for zcip taking into account all the
hints given so far on the list.
I've applied just the more obvious busyboxifications so maybe it could be
optimized more.
There are a few changes regarding xsetenv() from libbb/setup_enviroment.c,
which is now made available in libbb.h. Maybe this could be a separate patch.
BTW.: the only test i've done is to compile it as i know nothing about how
zcip works. ;-) so the zcip gurus should please test it.
Size reduction is:
root at localhost:/dev/pts/3:/root/Desktop/busybox-1.00/networking# size zcip.o.orig
text data bss dec hex filename
2587 0 8 2595 a23 zcip.o.orig
root at localhost:/dev/pts/3:/root/Desktop/busybox-1.00/networking# size zcip.o
text data bss dec hex filename
2372 0 0 2372 944 zcip.o
root at localhost:/dev/pts/3:/root/Desktop/busybox-1.00/networking#
This patch applies on top of previous bb-zcip0418.patch.
Ciao,
Tito
-------------- next part --------------
--- networking/zcip_orig.c 2005-04-18 21:38:26.000000000 +0200
+++ networking/zcip.c 2005-04-19 20:42:05.000000000 +0200
@@ -31,14 +31,12 @@
* certainly be used. Its naming is built over multicast DNS.
*/
-// #define DEBUG
-
-// TODO:
-// - more real-world usage/testing, especially daemon mode
-// - kernel packet filters to reduce scheduling noise
-// - avoid silent script failures, especially under load...
-// - link status monitoring (restart on link-up; stop on link-down)
-
+/* TODO:
+ - more real-world usage/testing, especially daemon mode
+ - kernel packet filters to reduce scheduling noise
+ - avoid silent script failures, especially under load...
+ - link status monitoring (restart on link-up; stop on link-down)
+*/
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
@@ -63,11 +61,12 @@
#include <linux/if_packet.h>
#include <linux/sockios.h>
-
+#include "busybox.h"
+#include "libbb.h"
struct arp_packet {
struct ether_header hdr;
- // FIXME this part is netinet/if_ether.h "struct ether_arp"
+ /* FIXME this part is netinet/if_ether.h "struct ether_arp" */
struct arphdr arp;
struct ether_addr source_addr;
struct in_addr source_ip;
@@ -90,29 +89,13 @@
static const unsigned ANNOUNCE_INTERVAL = 2;
static const time_t DEFEND_INTERVAL = 10;
-static const unsigned char ZCIP_VERSION[] = "0.75 (18 April 2005)";
-static char *prog;
+#define ZCIP_VERSION "0.75 (18 April 2005)"
static const struct in_addr null_ip = { 0 };
static const struct ether_addr null_addr = { {0, 0, 0, 0, 0, 0} };
-static int verbose = 0;
-
-#ifdef DEBUG
-
-#define DBG(fmt,args...) \
- fprintf(stderr, "%s: " fmt , prog , ## args)
-#define VDBG(fmt,args...) do { \
- if (verbose) fprintf(stderr, "%s: " fmt , prog ,## args); \
- } while (0)
-#else
-
-#define DBG(fmt,args...) \
- do { } while (0)
-#define VDBG DBG
-#endif /* DEBUG */
-/**
+/*
* Pick a random link local IP address on 169.254/16, except that
* the first and last 256 addresses are reserved.
*/
@@ -128,7 +111,7 @@
ip->s_addr = htonl((LINKLOCAL_ADDR + 0x0100) + tmp);
}
-/**
+/*
* Broadcast an ARP packet.
*/
static int
@@ -138,12 +121,12 @@
{
struct arp_packet p;
- // ether header
+ /* ether header */
p.hdr.ether_type = htons(ETHERTYPE_ARP);
memcpy(p.hdr.ether_shost, source_addr, ETH_ALEN);
memset(p.hdr.ether_dhost, 0xff, ETH_ALEN);
- // arp request
+ /* arp request */
p.arp.ar_hrd = htons(ARPHRD_ETHER);
p.arp.ar_pro = htons(ETHERTYPE_IP);
p.arp.ar_hln = ETH_ALEN;
@@ -154,15 +137,15 @@
memcpy(&p.target_addr, target_addr, ETH_ALEN);
memcpy(&p.target_ip, &target_ip, sizeof (p.target_ip));
- // send it
+ /* send it */
if (sendto(fd, &p, sizeof (p), 0, saddr, sizeof (*saddr)) < 0) {
- perror("sendto");
+ bb_perror_msg("sendto");
return -errno;
}
return 0;
}
-/**
+/*
* Run a script.
*/
static int
@@ -172,21 +155,19 @@
char *why;
if (script != NULL) {
- VDBG("%s run %s %s\n", intf, script, arg);
if (ip != NULL) {
char *addr = inet_ntoa(*ip);
- setenv("ip", addr, 1);
+ xsetenv("ip", addr);
syslog(LOG_INFO, "%s %s %s", arg, intf, addr);
}
pid = vfork();
- if (pid < 0) { // error
+ if (pid < 0) { /* error */
why = "vfork";
goto bad;
- } else if (pid == 0) { // child
+ } else if (pid == 0) { /* child */
execl(script, script, arg, NULL);
- perror("execl");
- _exit(EXIT_FAILURE);
+ bb_perror_msg_and_die("execl");
}
if (waitpid(pid, &status, 0) <= 0) {
@@ -194,8 +175,7 @@
goto bad;
}
if (WEXITSTATUS(status) != 0) {
- fprintf(stderr, "%s: script %s failed, exit=%d\n",
- prog, script, WEXITSTATUS(status));
+ bb_perror_msg("script %s failed, exit=%d", script, WEXITSTATUS(status));
return -errno;
}
}
@@ -207,31 +187,7 @@
return status;
}
-#ifndef NO_BUSYBOX
-#include "busybox.h"
-#endif
-
-/**
- * Print usage information.
- */
-static void __attribute__ ((noreturn))
-usage(const char *msg)
-{
- fprintf(stderr, "%s: %s\n", prog, msg);
-#ifdef NO_BUSYBOX
- fprintf(stderr, "Usage: %s [OPTIONS] ifname script\n"
- "\t-f foreground mode (implied by -v)\n"
- "\t-q quit after address (no daemon)\n"
- "\t-r 169.254.x.x request this address first\n"
- "\t-v verbose; show version\n",
- prog);
- exit(0);
-#else
- bb_show_usage();
-#endif
-}
-
-/**
+/*
* Return milliseconds of random delay, up to "secs" seconds.
*/
static inline unsigned
@@ -240,85 +196,72 @@
return lrand48() % (secs * 1000);
}
-/**
+/*
* main program
*/
-int
-main(int argc, char *argv[])
- __attribute__ ((weak, alias ("zcip_main")));
+
+#define FOREGROUND 1
+#define QUIT 2
+#define REQUEST 4
+#define VERBOSE 8
int zcip_main(int argc, char *argv[])
{
char *intf = NULL;
char *script = NULL;
- int quit = 0;
- int foreground = 0;
-
char *why;
struct sockaddr saddr;
struct ether_addr addr;
struct in_addr ip = { 0 };
int fd;
int ready = 0;
- suseconds_t timeout = 0; // milliseconds
+ suseconds_t timeout = 0; /* milliseconds */
time_t defend = 0;
unsigned conflicts = 0;
unsigned nprobes = 0;
unsigned nclaims = 0;
- int t;
+ unsigned long t;
- // parse commandline: prog [options] ifname script
- prog = argv[0];
- while ((t = getopt(argc, argv, "fqr:v")) != EOF) {
- switch (t) {
- case 'f':
- foreground = 1;
- continue;
- case 'q':
- quit = 1;
- continue;
- case 'r':
- if (inet_aton(optarg, &ip) == 0
- || (ntohl(ip.s_addr) & IN_CLASSB_NET)
- != LINKLOCAL_ADDR) {
- usage("invalid link address");
- }
- continue;
- case 'v':
- if (!verbose)
- printf("%s: version %s\n", prog, ZCIP_VERSION);
- verbose++;
- foreground = 1;
- continue;
- default:
- usage("bad option");
- }
+ bb_opt_complementaly = "vf";
+ /* parse commandline: prog [options] ifname script */
+ t = bb_getopt_ulflags(argc, argv, "fqr:v", &why); /* reuse char* why */
+
+ argc -= optind;
+ argv += optind;
+
+ if ((t & 0x80000000UL) || (argc < 1) || (argc > 2)) {
+ bb_show_usage();
+ }
+
+ if (t & VERBOSE) {
+ bb_printf("%s: version %s\n", bb_applet_name, ZCIP_VERSION);
}
- if (optind < argc - 1) {
- intf = argv[optind++];
- setenv("interface", intf, 1);
- script = argv[optind++];
+ if ((t & REQUEST) && (inet_aton(why, &ip) == 0 || (ntohl(ip.s_addr) & IN_CLASSB_NET) != LINKLOCAL_ADDR)) {
+ bb_perror_msg_and_die("invalid link address");
}
- if (optind != argc || !intf)
- usage("wrong number of arguments");
- openlog(prog, 0, LOG_DAEMON);
+
+ intf = argv[0];
+ xsetenv("interface", intf);
+ script = argv[1];
+
+ openlog(bb_applet_name, 0, LOG_DAEMON);
- // initialize the interface (modprobe, ifup, etc)
+ /* initialize the interface (modprobe, ifup, etc) */
if (run(script, "init", intf, NULL) < 0)
return EXIT_FAILURE;
- // initialize saddr
+ /* initialize saddr */
memset(&saddr, 0, sizeof (saddr));
strncpy(saddr.sa_data, intf, sizeof (saddr.sa_data));
- // open an ARP socket
+ /* open an ARP socket */
if ((fd = socket(PF_PACKET, SOCK_PACKET, htons(ETH_P_ARP))) < 0) {
why = "open";
fail:
- foreground = 1;
+ t |= FOREGROUND;
goto bad;
}
- // bind to the interface's ARP socket
+ /* bind to the interface's ARP socket */
if (bind(fd, &saddr, sizeof (saddr)) < 0) {
why = "bind";
goto fail;
@@ -326,7 +269,7 @@
struct ifreq ifr;
short seed[3];
- // get the interface's ethernet address
+ /* get the interface's ethernet address */
memset(&ifr, 0, sizeof (ifr));
strncpy(ifr.ifr_name, intf, sizeof (ifr.ifr_name));
if (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0) {
@@ -335,37 +278,37 @@
}
memcpy(&addr, &ifr.ifr_hwaddr.sa_data, ETH_ALEN);
- // start with some stable ip address, either a function of
- // the hardware address or else the last address we used.
- // NOTE: the sequence of addresses we try changes only
- // depending on when we detect conflicts.
+ /* start with some stable ip address, either a function of
+ the hardware address or else the last address we used.
+ NOTE: the sequence of addresses we try changes only
+ depending on when we detect conflicts. */
memcpy(seed, &ifr.ifr_hwaddr.sa_data, ETH_ALEN);
seed48(seed);
if (ip.s_addr == 0)
pick(&ip);
}
- // FIXME cases to handle:
- // - zcip already running!
- // - link already has local address... just defend/update
-
- // daemonize now; don't delay system startup
- if (!foreground) {
- if (daemon(0, verbose) < 0) {
+ /* FIXME cases to handle:
+ - zcip already running!
+ - link already has local address... just defend/update */
+
+ /* daemonize now; don't delay system startup */
+ if (!(t & FOREGROUND)) {
+ if (daemon(0, (t & VERBOSE)) < 0) {
why = "daemon";
goto bad;
}
syslog(LOG_INFO, "start, interface %s", intf);
}
- // run the dynamic address negotiation protocol,
- // restarting after address conflicts:
- // - start with some address we want to try
- // - short random delay
- // - arp probes to see if another host else uses it
- // - arp announcements that we're claiming it
- // - use it
- // - defend it, within limits
+ /* run the dynamic address negotiation protocol,
+ restarting after address conflicts:
+ - start with some address we want to try
+ - short random delay
+ - arp probes to see if another host else uses it
+ - arp announcements that we're claiming it
+ - use it
+ - defend it, within limits */
while (1) {
struct pollfd fds[1];
struct timeval tv1;
@@ -375,7 +318,7 @@
fds[0].events = POLLIN;
fds[0].revents = 0;
- // poll, being ready to adjust current timeout
+ /* poll, being ready to adjust current timeout */
if (timeout > 0) {
gettimeofday(&tv1, NULL);
tv1.tv_usec += (timeout % 1000) * 1000;
@@ -386,21 +329,17 @@
tv1.tv_sec += timeout / 1000;
} else if (timeout == 0) {
timeout = ms_rdelay(PROBE_WAIT);
- // FIXME setsockopt(fd, SO_ATTACH_FILTER, ...) to
- // make the kernel filter out all packets except
- // ones we'd care about.
+ /* FIXME setsockopt(fd, SO_ATTACH_FILTER, ...) to
+ make the kernel filter out all packets except
+ ones we'd care about. */
}
- VDBG("...wait %ld %s nprobes=%d, nclaims=%d\n",
- timeout, intf, nprobes, nclaims);
switch (poll(fds, 1, timeout)) {
- // timeouts trigger protocol transitions
+ /* timeouts trigger protocol transitions */
case 0:
- // probes
+ /* probes */
if (nprobes < PROBE_NUM) {
nprobes++;
- VDBG("probe/%d %s@%s\n",
- nprobes, intf, inet_ntoa(ip));
(void)arp(fd, &saddr, ARPOP_REQUEST,
&addr, null_ip,
&null_addr, ip);
@@ -411,38 +350,36 @@
} else
timeout = ANNOUNCE_WAIT * 1000;
}
- // then announcements
+ /* then announcements */
else if (nclaims < ANNOUNCE_NUM) {
nclaims++;
- VDBG("announce/%d %s@%s\n",
- nclaims, intf, inet_ntoa(ip));
(void)arp(fd, &saddr, ARPOP_REQUEST,
&addr, ip,
&addr, ip);
if (nclaims < ANNOUNCE_NUM) {
timeout = ANNOUNCE_INTERVAL * 1000;
} else {
- // link is ok to use earlier
+ /* link is ok to use earlier */
run(script, "config", intf, &ip);
ready = 1;
conflicts = 0;
timeout = -1;
- // NOTE: all other exit paths
- // should deconfig ...
- if (quit)
+ /* NOTE: all other exit paths
+ should deconfig ... */
+ if (t & QUIT)
return EXIT_SUCCESS;
- // FIXME update filters
+ /* FIXME update filters */
}
}
break;
- // packets arriving
+ /* packets arriving */
case 1:
- // maybe adjust timeout
+ /* maybe adjust timeout */
if (timeout > 0) {
struct timeval tv2;
-
+
gettimeofday(&tv2, NULL);
if (timercmp(&tv1, &tv2, <)) {
timeout = -1;
@@ -454,46 +391,33 @@
}
if ((fds[0].revents & POLLIN) == 0) {
if (fds[0].revents & POLLERR) {
- // FIXME: links routinely go down;
- // this shouldn't necessarily exit.
- fprintf(stderr, "%s %s: poll error\n",
- prog, intf);
+ /* FIXME: links routinely go down;
+ this shouldn't necessarily exit. */
+ bb_perror_msg("%s: poll error", intf);
if (ready) {
- run(script, "deconfig",
- intf, &ip);
+ run(script, "deconfig", intf, &ip);
}
return EXIT_FAILURE;
}
continue;
}
- // read ARP packet
+ /* read ARP packet */
if (recv(fd, &p, sizeof (p), 0) < 0) {
why = "recv";
goto bad;
}
if (p.hdr.ether_type != htons(ETHERTYPE_ARP))
continue;
-
- VDBG("%s recv arp type=%d, op=%d,\n",
- intf, ntohs(p.hdr.ether_type),
- ntohs(p.arp.ar_op));
- VDBG("\tsource=%s %s\n",
- ether_ntoa(&p.source_addr),
- inet_ntoa(p.source_ip));
- VDBG("\ttarget=%s %s\n",
- ether_ntoa(&p.target_addr),
- inet_ntoa(p.target_ip));
+
if (p.arp.ar_op != htons(ARPOP_REQUEST)
&& p.arp.ar_op != htons(ARPOP_REPLY))
continue;
- // some cases are always conflicts
+ /* some cases are always conflicts */
if ((p.source_ip.s_addr == ip.s_addr)
&& (memcmp(&addr, &p.source_addr,
ETH_ALEN) != 0)) {
collision:
- VDBG("%s ARP conflict from %s\n", intf,
- ether_ntoa(&p.source_addr));
if (ready) {
time_t now = time(0);
@@ -504,28 +428,26 @@
ARPOP_REQUEST,
&addr, ip,
&addr, ip);
- VDBG("%s defend\n", intf);
timeout = -1;
continue;
}
defend = now;
ready = 0;
run(script, "deconfig", intf, &ip);
- // FIXME rm filters: setsockopt(fd,
- // SO_DETACH_FILTER, ...)
+ /* FIXME rm filters: setsockopt(fd,
+ SO_DETACH_FILTER, ...) */
}
conflicts++;
if (conflicts >= MAX_CONFLICTS) {
- VDBG("%s ratelimit\n", intf);
sleep(RATE_LIMIT_INTERVAL);
}
- // restart the whole protocol
+ /* restart the whole protocol */
pick(&ip);
timeout = 0;
nprobes = 0;
nclaims = 0;
}
- // two hosts probing one address is a collision too
+ /* two hosts probing one address is a collision too */
else if (p.target_ip.s_addr == ip.s_addr
&& nclaims == 0
&& p.arp.ar_op == htons(ARPOP_REQUEST)
@@ -541,10 +463,11 @@
}
}
bad:
- if (foreground)
- perror(why);
- else
+ if ( t & FOREGROUND) {
+ bb_perror_msg(why);
+ } else {
syslog(LOG_ERR, "%s %s, %s error: %s",
- prog, intf, why, strerror(errno));
+ bb_applet_name, intf, why, strerror(errno));
+ }
return EXIT_FAILURE;
}
--- libbb/setup_environment_orig.c 2004-03-15 09:28:43.000000000 +0100
+++ libbb/setup_environment.c 2005-04-19 20:38:04.000000000 +0200
@@ -42,7 +42,7 @@
#define DEFAULT_LOGIN_PATH "/bin:/usr/bin"
#define DEFAULT_ROOT_LOGIN_PATH "/usr/sbin:/bin:/usr/bin:/sbin"
-static void xsetenv ( const char *key, const char *value )
+void xsetenv ( const char *key, const char *value )
{
if ( setenv ( key, value, 1 ))
bb_error_msg_and_die (bb_msg_memory_exhausted);
--- include/libbb_orig.h 2004-09-15 05:04:07.000000000 +0200
+++ include/libbb.h 2005-04-19 20:34:48.000000000 +0200
@@ -428,6 +428,7 @@
);
extern int run_parts(char **args, const unsigned char test_mode, char **env);
extern int restricted_shell ( const char *shell );
+extern void xsetenv ( const char *key, const char *value );
extern void setup_environment ( const char *shell, int loginshell, int changeenv, const struct passwd *pw );
extern int correct_password ( const struct passwd *pw );
extern char *pw_encrypt(const char *clear, const char *salt);
More information about the busybox
mailing list