aboutsummaryrefslogtreecommitdiff
path: root/networking/zcip.c
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2008-10-10 11:28:39 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2008-10-10 11:28:39 +0000
commitcdd1f732bc5b8447dd12b59613663b7d08fce20b (patch)
tree444fb892e563673181a8debcf32620658da97729 /networking/zcip.c
parentafd7a8d744b29daaedbba1969307bd9ce17e7dc3 (diff)
downloadbusybox-w32-cdd1f732bc5b8447dd12b59613663b7d08fce20b.tar.gz
busybox-w32-cdd1f732bc5b8447dd12b59613663b7d08fce20b.tar.bz2
busybox-w32-cdd1f732bc5b8447dd12b59613663b7d08fce20b.zip
zcip: code size optimizations, improved help text and comments
function old new delta packed_usage 24750 24787 +37 run 658 655 -3 pick 40 34 -6 arp 186 177 -9 zcip_main 1402 1356 -46 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/4 up/down: 37/-64) Total: -27 bytes
Diffstat (limited to 'networking/zcip.c')
-rw-r--r--networking/zcip.c141
1 files changed, 79 insertions, 62 deletions
diff --git a/networking/zcip.c b/networking/zcip.c
index f406b6c16..ff9c83dc7 100644
--- a/networking/zcip.c
+++ b/networking/zcip.c
@@ -75,35 +75,40 @@ enum {
75}; 75};
76 76
77struct globals { 77struct globals {
78 char *intf;
79 struct sockaddr saddr; 78 struct sockaddr saddr;
79 struct ether_addr eth_addr;
80}; 80};
81#define G (*(struct globals*)&bb_common_bufsiz1) 81#define G (*(struct globals*)&bb_common_bufsiz1)
82#define intf (G.intf ) 82#define saddr (G.saddr )
83#define saddr (G.saddr) 83#define eth_addr (G.eth_addr)
84 84
85 85
86/** 86/**
87 * Pick a random link local IP address on 169.254/16, except that 87 * Pick a random link local IP address on 169.254/16, except that
88 * the first and last 256 addresses are reserved. 88 * the first and last 256 addresses are reserved.
89 */ 89 */
90static void pick(struct in_addr *ip) 90static uint32_t pick(void)
91{ 91{
92 unsigned tmp; 92 unsigned tmp;
93 93
94 do { 94 do {
95 tmp = rand() & IN_CLASSB_HOST; 95 tmp = rand() & IN_CLASSB_HOST;
96 } while (tmp > (IN_CLASSB_HOST - 0x0200)); 96 } while (tmp > (IN_CLASSB_HOST - 0x0200));
97 ip->s_addr = htonl((LINKLOCAL_ADDR + 0x0100) + tmp); 97 return htonl((LINKLOCAL_ADDR + 0x0100) + tmp);
98} 98}
99 99
100/** 100/**
101 * Broadcast an ARP packet. 101 * Broadcast an ARP packet.
102 */ 102 */
103static void arp(int op, 103static void arp(
104 const struct ether_addr *source_eth, struct in_addr source_ip, 104 /* int op, - always ARPOP_REQUEST */
105 /* const struct ether_addr *source_eth, - always &eth_addr */
106 struct in_addr source_ip,
105 const struct ether_addr *target_eth, struct in_addr target_ip) 107 const struct ether_addr *target_eth, struct in_addr target_ip)
106{ 108{
109 enum { op = ARPOP_REQUEST };
110#define source_eth (&eth_addr)
111
107 struct arp_packet p; 112 struct arp_packet p;
108 memset(&p, 0, sizeof(p)); 113 memset(&p, 0, sizeof(p));
109 114
@@ -124,38 +129,44 @@ static void arp(int op,
124 memcpy(&p.arp.arp_tpa, &target_ip, sizeof(p.arp.arp_tpa)); 129 memcpy(&p.arp.arp_tpa, &target_ip, sizeof(p.arp.arp_tpa));
125 130
126 // send it 131 // send it
132 // Even though sock_fd is already bound to saddr, just send()
133 // won't work, because "socket is not connected"
134 // (and connect() won't fix that, "operation not supported").
135 // Thus we sendto() to saddr. I wonder which sockaddr
136 // (from bind() or from sendto()?) kernel actually uses
137 // to determine iface to emit the packet from...
127 xsendto(sock_fd, &p, sizeof(p), &saddr, sizeof(saddr)); 138 xsendto(sock_fd, &p, sizeof(p), &saddr, sizeof(saddr));
128 139#undef source_eth
129 // Currently all callers ignore errors, that's why returns are
130 // commented out...
131 //return 0;
132} 140}
133 141
134/** 142/**
135 * Run a script. argv[2] is already NULL. 143 * Run a script.
144 * argv[0]:intf argv[1]:script_name argv[2]:junk argv[3]:NULL
136 */ 145 */
137static int run(char *argv[3], struct in_addr *ip) 146static int run(char *argv[3], const char *param, struct in_addr *ip)
138{ 147{
139 int status; 148 int status;
140 char *addr = addr; /* for gcc */ 149 char *addr = addr; /* for gcc */
141 const char *fmt = "%s %s %s" + 3; 150 const char *fmt = "%s %s %s" + 3;
142 151
143 VDBG("%s run %s %s\n", intf, argv[0], argv[1]); 152 argv[2] = (char*)param;
153
154 VDBG("%s run %s %s\n", argv[0], argv[1], argv[2]);
144 155
145 if (ip) { 156 if (ip) {
146 addr = inet_ntoa(*ip); 157 addr = inet_ntoa(*ip);
147 xsetenv("ip", addr); 158 xsetenv("ip", addr);
148 fmt -= 3; 159 fmt -= 3;
149 } 160 }
150 bb_info_msg(fmt, argv[1], intf, addr); 161 bb_info_msg(fmt, argv[2], argv[0], addr);
151 162
152 status = wait4pid(spawn(argv)); 163 status = wait4pid(spawn(argv + 1));
153 if (status < 0) { 164 if (status < 0) {
154 bb_perror_msg("%s %s %s" + 3, argv[1], intf); 165 bb_perror_msg("%s %s %s" + 3, argv[2], argv[0]);
155 return -errno; 166 return -errno;
156 } 167 }
157 if (status != 0) 168 if (status != 0)
158 bb_error_msg("script %s %s failed, exitcode=%d", argv[0], argv[1], status); 169 bb_error_msg("script %s %s failed, exitcode=%d", argv[1], argv[2], status);
159 return status; 170 return status;
160} 171}
161 172
@@ -173,8 +184,7 @@ static ALWAYS_INLINE unsigned random_delay_ms(unsigned secs)
173int zcip_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 184int zcip_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
174int zcip_main(int argc, char **argv) 185int zcip_main(int argc, char **argv)
175{ 186{
176 int state = PROBE; 187 int state;
177 struct ether_addr eth_addr;
178 char *r_opt; 188 char *r_opt;
179 unsigned opts; 189 unsigned opts;
180 190
@@ -184,7 +194,6 @@ int zcip_main(int argc, char **argv)
184 const struct ether_addr null_addr; 194 const struct ether_addr null_addr;
185 struct in_addr ip; 195 struct in_addr ip;
186 struct ifreq ifr; 196 struct ifreq ifr;
187 char *script_av[3];
188 int timeout_ms; /* must be signed */ 197 int timeout_ms; /* must be signed */
189 unsigned conflicts; 198 unsigned conflicts;
190 unsigned nprobes; 199 unsigned nprobes;
@@ -196,7 +205,6 @@ int zcip_main(int argc, char **argv)
196#define null_addr (L.null_addr ) 205#define null_addr (L.null_addr )
197#define ip (L.ip ) 206#define ip (L.ip )
198#define ifr (L.ifr ) 207#define ifr (L.ifr )
199#define script_av (L.script_av )
200#define timeout_ms (L.timeout_ms) 208#define timeout_ms (L.timeout_ms)
201#define conflicts (L.conflicts ) 209#define conflicts (L.conflicts )
202#define nprobes (L.nprobes ) 210#define nprobes (L.nprobes )
@@ -234,29 +242,33 @@ int zcip_main(int argc, char **argv)
234 } 242 }
235 } 243 }
236 argc -= optind; 244 argc -= optind;
237 argv += optind; 245 argv += optind - 1;
246
247 /* Now: argv[0]:junk argv[1]:intf argv[2]:script argv[3]:NULL */
248 /* We need to make space for script argument: */
249 argv[0] = argv[1];
250 argv[1] = argv[2];
251 /* Now: argv[0]:intf argv[1]:script argv[2]:junk argv[3]:NULL */
252#define argv_intf (argv[0])
238 253
239 intf = argv[0]; 254 xsetenv("interface", argv_intf);
240 script_av[0] = argv[1];
241 xsetenv("interface", intf);
242 255
243 // initialize the interface (modprobe, ifup, etc) 256 // initialize the interface (modprobe, ifup, etc)
244 script_av[1] = (char*)"init"; 257 if (run(argv, "init", NULL))
245 if (run(script_av, NULL))
246 return EXIT_FAILURE; 258 return EXIT_FAILURE;
247 259
248 // initialize saddr 260 // initialize saddr
249 // saddr is: { u16 sa_family; u8 sa_data[14]; } 261 // saddr is: { u16 sa_family; u8 sa_data[14]; }
250 //memset(&saddr, 0, sizeof(saddr)); 262 //memset(&saddr, 0, sizeof(saddr));
251 //TODO: are we leaving sa_family == 0 (AF_UNSPEC)?! 263 //TODO: are we leaving sa_family == 0 (AF_UNSPEC)?!
252 safe_strncpy(saddr.sa_data, intf, sizeof(saddr.sa_data)); 264 safe_strncpy(saddr.sa_data, argv_intf, sizeof(saddr.sa_data));
253 265
254 // bind to the interface's ARP socket 266 // bind to the interface's ARP socket
255 xbind(sock_fd, &saddr, sizeof(saddr)); 267 xbind(sock_fd, &saddr, sizeof(saddr));
256 268
257 // get the interface's ethernet address 269 // get the interface's ethernet address
258 //memset(&ifr, 0, sizeof(ifr)); 270 //memset(&ifr, 0, sizeof(ifr));
259 strncpy(ifr.ifr_name, intf, sizeof(ifr.ifr_name)); 271 strncpy(ifr.ifr_name, argv_intf, sizeof(ifr.ifr_name));
260 xioctl(sock_fd, SIOCGIFHWADDR, &ifr); 272 xioctl(sock_fd, SIOCGIFHWADDR, &ifr);
261 memcpy(&eth_addr, &ifr.ifr_hwaddr.sa_data, ETH_ALEN); 273 memcpy(&eth_addr, &ifr.ifr_hwaddr.sa_data, ETH_ALEN);
262 274
@@ -267,12 +279,11 @@ int zcip_main(int argc, char **argv)
267 // NOTE: the sequence of addresses we try changes only 279 // NOTE: the sequence of addresses we try changes only
268 // depending on when we detect conflicts. 280 // depending on when we detect conflicts.
269 { 281 {
270 uint32_t t; 282 uint32_t t = get_unaligned_u32p((uint32_t *) ((char *)&eth_addr + 2));
271 memcpy(&t, (char*)&eth_addr + 2, 4);
272 srand(t); 283 srand(t);
273 } 284 }
274 if (ip.s_addr == 0) 285 if (ip.s_addr == 0)
275 pick(&ip); 286 ip.s_addr = pick();
276 287
277 // FIXME cases to handle: 288 // FIXME cases to handle:
278 // - zcip already running! 289 // - zcip already running!
@@ -283,7 +294,7 @@ int zcip_main(int argc, char **argv)
283#if BB_MMU 294#if BB_MMU
284 bb_daemonize(0 /*was: DAEMON_CHDIR_ROOT*/); 295 bb_daemonize(0 /*was: DAEMON_CHDIR_ROOT*/);
285#endif 296#endif
286 bb_info_msg("start, interface %s", intf); 297 bb_info_msg("start, interface %s", argv_intf);
287 } 298 }
288 299
289 // run the dynamic address negotiation protocol, 300 // run the dynamic address negotiation protocol,
@@ -294,6 +305,14 @@ int zcip_main(int argc, char **argv)
294 // - arp announcements that we're claiming it 305 // - arp announcements that we're claiming it
295 // - use it 306 // - use it
296 // - defend it, within limits 307 // - defend it, within limits
308 // exit if:
309 // - address is successfully obtained and -q was given:
310 // run "<script> config", then exit with exitcode 0
311 // - poll error (when does this happen?)
312 // - read error (when does this happen?)
313 // - sendto error (in arp()) (when does this happen?)
314 // - revents & POLLERR (link down). run "<script> deconfig" first
315 state = PROBE;
297 while (1) { 316 while (1) {
298 struct pollfd fds[1]; 317 struct pollfd fds[1];
299 unsigned deadline_us; 318 unsigned deadline_us;
@@ -316,7 +335,7 @@ int zcip_main(int argc, char **argv)
316 deadline_us = MONOTONIC_US() + timeout_ms * 1000; 335 deadline_us = MONOTONIC_US() + timeout_ms * 1000;
317 336
318 VDBG("...wait %d %s nprobes=%u, nclaims=%u\n", 337 VDBG("...wait %d %s nprobes=%u, nclaims=%u\n",
319 timeout_ms, intf, nprobes, nclaims); 338 timeout_ms, argv_intf, nprobes, nclaims);
320 339
321 switch (safe_poll(fds, 1, timeout_ms)) { 340 switch (safe_poll(fds, 1, timeout_ms)) {
322 341
@@ -334,9 +353,9 @@ int zcip_main(int argc, char **argv)
334 if (nprobes < PROBE_NUM) { 353 if (nprobes < PROBE_NUM) {
335 nprobes++; 354 nprobes++;
336 VDBG("probe/%u %s@%s\n", 355 VDBG("probe/%u %s@%s\n",
337 nprobes, intf, inet_ntoa(ip)); 356 nprobes, argv_intf, inet_ntoa(ip));
338 arp(ARPOP_REQUEST, 357 arp(/* ARPOP_REQUEST, */
339 &eth_addr, null_ip, 358 /* &eth_addr, */ null_ip,
340 &null_addr, ip); 359 &null_addr, ip);
341 timeout_ms = PROBE_MIN * 1000; 360 timeout_ms = PROBE_MIN * 1000;
342 timeout_ms += random_delay_ms(PROBE_MAX - PROBE_MIN); 361 timeout_ms += random_delay_ms(PROBE_MAX - PROBE_MIN);
@@ -346,9 +365,9 @@ int zcip_main(int argc, char **argv)
346 state = ANNOUNCE; 365 state = ANNOUNCE;
347 nclaims = 0; 366 nclaims = 0;
348 VDBG("announce/%u %s@%s\n", 367 VDBG("announce/%u %s@%s\n",
349 nclaims, intf, inet_ntoa(ip)); 368 nclaims, argv_intf, inet_ntoa(ip));
350 arp(ARPOP_REQUEST, 369 arp(/* ARPOP_REQUEST, */
351 &eth_addr, ip, 370 /* &eth_addr, */ ip,
352 &eth_addr, ip); 371 &eth_addr, ip);
353 timeout_ms = ANNOUNCE_INTERVAL * 1000; 372 timeout_ms = ANNOUNCE_INTERVAL * 1000;
354 } 373 }
@@ -359,9 +378,9 @@ int zcip_main(int argc, char **argv)
359 state = ANNOUNCE; 378 state = ANNOUNCE;
360 nclaims = 0; 379 nclaims = 0;
361 VDBG("announce/%u %s@%s\n", 380 VDBG("announce/%u %s@%s\n",
362 nclaims, intf, inet_ntoa(ip)); 381 nclaims, argv_intf, inet_ntoa(ip));
363 arp(ARPOP_REQUEST, 382 arp(/* ARPOP_REQUEST, */
364 &eth_addr, ip, 383 /* &eth_addr, */ ip,
365 &eth_addr, ip); 384 &eth_addr, ip);
366 timeout_ms = ANNOUNCE_INTERVAL * 1000; 385 timeout_ms = ANNOUNCE_INTERVAL * 1000;
367 break; 386 break;
@@ -371,9 +390,9 @@ int zcip_main(int argc, char **argv)
371 if (nclaims < ANNOUNCE_NUM) { 390 if (nclaims < ANNOUNCE_NUM) {
372 nclaims++; 391 nclaims++;
373 VDBG("announce/%u %s@%s\n", 392 VDBG("announce/%u %s@%s\n",
374 nclaims, intf, inet_ntoa(ip)); 393 nclaims, argv_intf, inet_ntoa(ip));
375 arp(ARPOP_REQUEST, 394 arp(/* ARPOP_REQUEST, */
376 &eth_addr, ip, 395 /* &eth_addr, */ ip,
377 &eth_addr, ip); 396 &eth_addr, ip);
378 timeout_ms = ANNOUNCE_INTERVAL * 1000; 397 timeout_ms = ANNOUNCE_INTERVAL * 1000;
379 } 398 }
@@ -382,8 +401,7 @@ int zcip_main(int argc, char **argv)
382 state = MONITOR; 401 state = MONITOR;
383 // link is ok to use earlier 402 // link is ok to use earlier
384 // FIXME update filters 403 // FIXME update filters
385 script_av[1] = (char*)"config"; 404 run(argv, "config", &ip);
386 run(script_av, &ip);
387 ready = 1; 405 ready = 1;
388 conflicts = 0; 406 conflicts = 0;
389 timeout_ms = -1; // Never timeout in the monitor state. 407 timeout_ms = -1; // Never timeout in the monitor state.
@@ -403,7 +421,7 @@ int zcip_main(int argc, char **argv)
403 default: 421 default:
404 // Invalid, should never happen. Restart the whole protocol. 422 // Invalid, should never happen. Restart the whole protocol.
405 state = PROBE; 423 state = PROBE;
406 pick(&ip); 424 ip.s_addr = pick();
407 timeout_ms = 0; 425 timeout_ms = 0;
408 nprobes = 0; 426 nprobes = 0;
409 nclaims = 0; 427 nclaims = 0;
@@ -432,10 +450,9 @@ int zcip_main(int argc, char **argv)
432 if (fds[0].revents & POLLERR) { 450 if (fds[0].revents & POLLERR) {
433 // FIXME: links routinely go down; 451 // FIXME: links routinely go down;
434 // this shouldn't necessarily exit. 452 // this shouldn't necessarily exit.
435 bb_error_msg("iface %s is down", intf); 453 bb_error_msg("iface %s is down", argv_intf);
436 if (ready) { 454 if (ready) {
437 script_av[1] = (char*)"deconfig"; 455 run(argv, "deconfig", &ip);
438 run(script_av, &ip);
439 } 456 }
440 return EXIT_FAILURE; 457 return EXIT_FAILURE;
441 } 458 }
@@ -455,7 +472,7 @@ int zcip_main(int argc, char **argv)
455 struct in_addr *spa = (struct in_addr *) p.arp.arp_spa; 472 struct in_addr *spa = (struct in_addr *) p.arp.arp_spa;
456 struct in_addr *tpa = (struct in_addr *) p.arp.arp_tpa; 473 struct in_addr *tpa = (struct in_addr *) p.arp.arp_tpa;
457 VDBG("%s recv arp type=%d, op=%d,\n", 474 VDBG("%s recv arp type=%d, op=%d,\n",
458 intf, ntohs(p.eth.ether_type), 475 argv_intf, ntohs(p.eth.ether_type),
459 ntohs(p.arp.arp_op)); 476 ntohs(p.arp.arp_op));
460 VDBG("\tsource=%s %s\n", 477 VDBG("\tsource=%s %s\n",
461 ether_ntoa(sha), 478 ether_ntoa(sha),
@@ -494,13 +511,13 @@ int zcip_main(int argc, char **argv)
494 if (source_ip_conflict || target_ip_conflict) { 511 if (source_ip_conflict || target_ip_conflict) {
495 conflicts++; 512 conflicts++;
496 if (conflicts >= MAX_CONFLICTS) { 513 if (conflicts >= MAX_CONFLICTS) {
497 VDBG("%s ratelimit\n", intf); 514 VDBG("%s ratelimit\n", argv_intf);
498 timeout_ms = RATE_LIMIT_INTERVAL * 1000; 515 timeout_ms = RATE_LIMIT_INTERVAL * 1000;
499 state = RATE_LIMIT_PROBE; 516 state = RATE_LIMIT_PROBE;
500 } 517 }
501 518
502 // restart the whole protocol 519 // restart the whole protocol
503 pick(&ip); 520 ip.s_addr = pick();
504 timeout_ms = 0; 521 timeout_ms = 0;
505 nprobes = 0; 522 nprobes = 0;
506 nclaims = 0; 523 nclaims = 0;
@@ -512,8 +529,8 @@ int zcip_main(int argc, char **argv)
512 VDBG("monitor conflict -- defending\n"); 529 VDBG("monitor conflict -- defending\n");
513 state = DEFEND; 530 state = DEFEND;
514 timeout_ms = DEFEND_INTERVAL * 1000; 531 timeout_ms = DEFEND_INTERVAL * 1000;
515 arp(ARPOP_REQUEST, 532 arp(/* ARPOP_REQUEST, */
516 &eth_addr, ip, 533 /* &eth_addr, */ ip,
517 &eth_addr, ip); 534 &eth_addr, ip);
518 } 535 }
519 break; 536 break;
@@ -523,11 +540,10 @@ int zcip_main(int argc, char **argv)
523 state = PROBE; 540 state = PROBE;
524 VDBG("defend conflict -- starting over\n"); 541 VDBG("defend conflict -- starting over\n");
525 ready = 0; 542 ready = 0;
526 script_av[1] = (char*)"deconfig"; 543 run(argv, "deconfig", &ip);
527 run(script_av, &ip);
528 544
529 // restart the whole protocol 545 // restart the whole protocol
530 pick(&ip); 546 ip.s_addr = pick();
531 timeout_ms = 0; 547 timeout_ms = 0;
532 nprobes = 0; 548 nprobes = 0;
533 nclaims = 0; 549 nclaims = 0;
@@ -537,7 +553,7 @@ int zcip_main(int argc, char **argv)
537 // Invalid, should never happen. Restart the whole protocol. 553 // Invalid, should never happen. Restart the whole protocol.
538 VDBG("invalid state -- starting over\n"); 554 VDBG("invalid state -- starting over\n");
539 state = PROBE; 555 state = PROBE;
540 pick(&ip); 556 ip.s_addr = pick();
541 timeout_ms = 0; 557 timeout_ms = 0;
542 nprobes = 0; 558 nprobes = 0;
543 nclaims = 0; 559 nclaims = 0;
@@ -546,4 +562,5 @@ int zcip_main(int argc, char **argv)
546 break; // case 1 (packets arriving) 562 break; // case 1 (packets arriving)
547 } // switch poll 563 } // switch poll
548 } // while (1) 564 } // while (1)
565#undef argv_intf
549} 566}