aboutsummaryrefslogtreecommitdiff
path: root/networking/arping.c
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2007-06-17 19:09:05 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2007-06-17 19:09:05 +0000
commit459be35234cc24b69309eb0ee22600024c73713e (patch)
tree15ac4122d9c42ec75ba68d342827e37fcb1306ed /networking/arping.c
parente79dd06782175d50f639180cde5b2c56933aa2ee (diff)
downloadbusybox-w32-459be35234cc24b69309eb0ee22600024c73713e.tar.gz
busybox-w32-459be35234cc24b69309eb0ee22600024c73713e.tar.bz2
busybox-w32-459be35234cc24b69309eb0ee22600024c73713e.zip
hwclock: size optimizations
libbb/time.c: new file, introducing monotonic_us() pscan, traceroute, arping: use it instead of gettimeofday ping, zcip: TODO function old new delta monotonic_us - 89 +89 find_pair 164 180 +16 .rodata 129747 129763 +16 refresh 1144 1152 +8 ............ timeout 8 4 -4 static.start 8 4 -4 last 8 4 -4 parse_conf 1303 1284 -19 time_main 1149 1124 -25 gettimeofday_us 39 - -39 arping_main 2042 1969 -73 hwclock_main 594 501 -93 catcher 485 380 -105 traceroute_main 4300 4117 -183 ------------------------------------------------------------------------------ (add/remove: 2/1 grow/shrink: 8/11 up/down: 157/-562) Total: -405 bytes
Diffstat (limited to 'networking/arping.c')
-rw-r--r--networking/arping.c125
1 files changed, 55 insertions, 70 deletions
diff --git a/networking/arping.c b/networking/arping.c
index 1b2604902..a022e70ea 100644
--- a/networking/arping.c
+++ b/networking/arping.c
@@ -8,9 +8,6 @@
8 * Busybox port: Nick Fedchik <nick@fedchik.org.ua> 8 * Busybox port: Nick Fedchik <nick@fedchik.org.ua>
9 */ 9 */
10 10
11//#include <sys/ioctl.h>
12//#include <signal.h>
13
14#include <arpa/inet.h> 11#include <arpa/inet.h>
15#include <net/if.h> 12#include <net/if.h>
16#include <netinet/ether.h> 13#include <netinet/ether.h>
@@ -18,42 +15,42 @@
18 15
19#include "libbb.h" 16#include "libbb.h"
20 17
18/* We don't expect to see 1000+ seconds delay, unsigned is enough */
19#define MONOTONIC_US() ((unsigned)monotonic_us())
20
21static struct in_addr src; 21static struct in_addr src;
22static struct in_addr dst; 22static struct in_addr dst;
23static struct sockaddr_ll me; 23static struct sockaddr_ll me;
24static struct sockaddr_ll he; 24static struct sockaddr_ll he;
25static struct timeval last; 25static unsigned last;
26 26
27enum cfg_e { 27enum {
28 dad = 1, 28 DAD = 1,
29 unsolicited = 2, 29 UNSOLICITED = 2,
30 advert = 4, 30 ADVERT = 4,
31 quiet = 8, 31 QUIET = 8,
32 quit_on_reply = 16, 32 QUIT_ON_REPLY = 16,
33 broadcast_only = 32, 33 BCAST_ONLY = 32,
34 unicasting = 64 34 UNICASTING = 64
35}; 35};
36static int cfg; 36static int cfg;
37 37
38static int s; 38static int s;
39static unsigned count = UINT_MAX; 39static unsigned count = UINT_MAX;
40static unsigned timeout; 40static unsigned timeout_us;
41static int sent; 41static int sent;
42static int brd_sent; 42static int brd_sent;
43static int received; 43static int received;
44static int brd_recv; 44static int brd_recv;
45static int req_recv; 45static int req_recv;
46 46
47#define MS_TDIFF(tv1,tv2) ( ((tv1).tv_sec-(tv2).tv_sec)*1000 + \
48 ((tv1).tv_usec-(tv2).tv_usec)/1000 )
49
50static int send_pack(int sock, struct in_addr *src_addr, 47static int send_pack(int sock, struct in_addr *src_addr,
51 struct in_addr *dst_addr, struct sockaddr_ll *ME, 48 struct in_addr *dst_addr, struct sockaddr_ll *ME,
52 struct sockaddr_ll *HE) 49 struct sockaddr_ll *HE)
53{ 50{
54 int err; 51 int err;
55 struct timeval now; 52 unsigned now;
56 RESERVE_CONFIG_UBUFFER(buf, 256); 53 unsigned char buf[256];
57 struct arphdr *ah = (struct arphdr *) buf; 54 struct arphdr *ah = (struct arphdr *) buf;
58 unsigned char *p = (unsigned char *) (ah + 1); 55 unsigned char *p = (unsigned char *) (ah + 1);
59 56
@@ -62,7 +59,7 @@ static int send_pack(int sock, struct in_addr *src_addr,
62 ah->ar_pro = htons(ETH_P_IP); 59 ah->ar_pro = htons(ETH_P_IP);
63 ah->ar_hln = ME->sll_halen; 60 ah->ar_hln = ME->sll_halen;
64 ah->ar_pln = 4; 61 ah->ar_pln = 4;
65 ah->ar_op = cfg & advert ? htons(ARPOP_REPLY) : htons(ARPOP_REQUEST); 62 ah->ar_op = cfg & ADVERT ? htons(ARPOP_REPLY) : htons(ARPOP_REQUEST);
66 63
67 memcpy(p, &ME->sll_addr, ah->ar_hln); 64 memcpy(p, &ME->sll_addr, ah->ar_hln);
68 p += ME->sll_halen; 65 p += ME->sll_halen;
@@ -70,7 +67,7 @@ static int send_pack(int sock, struct in_addr *src_addr,
70 memcpy(p, src_addr, 4); 67 memcpy(p, src_addr, 4);
71 p += 4; 68 p += 4;
72 69
73 if (cfg & advert) 70 if (cfg & ADVERT)
74 memcpy(p, &ME->sll_addr, ah->ar_hln); 71 memcpy(p, &ME->sll_addr, ah->ar_hln);
75 else 72 else
76 memcpy(p, &HE->sll_addr, ah->ar_hln); 73 memcpy(p, &HE->sll_addr, ah->ar_hln);
@@ -79,21 +76,21 @@ static int send_pack(int sock, struct in_addr *src_addr,
79 memcpy(p, dst_addr, 4); 76 memcpy(p, dst_addr, 4);
80 p += 4; 77 p += 4;
81 78
82 gettimeofday(&now, NULL); 79 now = MONOTONIC_US();
83 err = sendto(sock, buf, p - buf, 0, (struct sockaddr *) HE, sizeof(*HE)); 80 err = sendto(sock, buf, p - buf, 0, (struct sockaddr *) HE, sizeof(*HE));
84 if (err == p - buf) { 81 if (err == p - buf) {
85 last = now; 82 last = now;
86 sent++; 83 sent++;
87 if (!(cfg & unicasting)) 84 if (!(cfg & UNICASTING))
88 brd_sent++; 85 brd_sent++;
89 } 86 }
90 RELEASE_CONFIG_BUFFER(buf);
91 return err; 87 return err;
92} 88}
93 89
90static void finish(void) ATTRIBUTE_NORETURN;
94static void finish(void) 91static void finish(void)
95{ 92{
96 if (!(cfg & quiet)) { 93 if (!(cfg & QUIET)) {
97 printf("Sent %d probe(s) (%d broadcast(s))\n" 94 printf("Sent %d probe(s) (%d broadcast(s))\n"
98 "Received %d repl%s" 95 "Received %d repl%s"
99 " (%d request(s), %d broadcast(s))\n", 96 " (%d request(s), %d broadcast(s))\n",
@@ -101,30 +98,31 @@ static void finish(void)
101 received, (received == 1) ? "ies" : "y", 98 received, (received == 1) ? "ies" : "y",
102 req_recv, brd_recv); 99 req_recv, brd_recv);
103 } 100 }
104 if (cfg & dad) 101 if (cfg & DAD)
105 exit(!!received); 102 exit(!!received);
106 if (cfg & unsolicited) 103 if (cfg & UNSOLICITED)
107 exit(0); 104 exit(0);
108 exit(!received); 105 exit(!received);
109} 106}
110 107
111static void catcher(void) 108static void catcher(void)
112{ 109{
113 struct timeval tv; 110 static unsigned start;
114 static struct timeval start;
115 111
116 gettimeofday(&tv, NULL); 112 unsigned now;
117 113
118 if (start.tv_sec == 0) 114 now = MONOTONIC_US();
119 start = tv; 115 if (start == 0)
116 start = now;
120 117
121 if (count-- == 0 118 if (count == 0 || (timeout_us && (now - start) > (timeout_us + 500000)))
122 || (timeout && MS_TDIFF(tv, start) > timeout * 1000 + 500))
123 finish(); 119 finish();
124 120
125 if (last.tv_sec == 0 || MS_TDIFF(tv, last) > 500) { 121 count--;
122
123 if (last == 0 || (now - last) > 500000) {
126 send_pack(s, &src, &dst, &me, &he); 124 send_pack(s, &src, &dst, &me, &he);
127 if (count == 0 && (cfg & unsolicited)) 125 if (count == 0 && (cfg & UNSOLICITED))
128 finish(); 126 finish();
129 } 127 }
130 alarm(1); 128 alarm(1);
@@ -162,7 +160,7 @@ static int recv_pack(unsigned char *buf, int len, struct sockaddr_ll *FROM)
162 return 0; 160 return 0;
163 memcpy(&src_ip, p + ah->ar_hln, 4); 161 memcpy(&src_ip, p + ah->ar_hln, 4);
164 memcpy(&dst_ip, p + ah->ar_hln + 4 + ah->ar_hln, 4); 162 memcpy(&dst_ip, p + ah->ar_hln + 4 + ah->ar_hln, 4);
165 if (!(cfg & dad)) { 163 if (!(cfg & DAD)) {
166 if (src_ip.s_addr != dst.s_addr) 164 if (src_ip.s_addr != dst.s_addr)
167 return 0; 165 return 0;
168 if (src.s_addr != dst_ip.s_addr) 166 if (src.s_addr != dst_ip.s_addr)
@@ -190,11 +188,8 @@ static int recv_pack(unsigned char *buf, int len, struct sockaddr_ll *FROM)
190 if (src.s_addr && src.s_addr != dst_ip.s_addr) 188 if (src.s_addr && src.s_addr != dst_ip.s_addr)
191 return 0; 189 return 0;
192 } 190 }
193 if (!(cfg & quiet)) { 191 if (!(cfg & QUIET)) {
194 int s_printed = 0; 192 int s_printed = 0;
195 struct timeval tv;
196
197 gettimeofday(&tv, NULL);
198 193
199 printf("%scast re%s from %s [%s]", 194 printf("%scast re%s from %s [%s]",
200 FROM->sll_pkttype == PACKET_HOST ? "Uni" : "Broad", 195 FROM->sll_pkttype == PACKET_HOST ? "Uni" : "Broad",
@@ -212,13 +207,8 @@ static int recv_pack(unsigned char *buf, int len, struct sockaddr_ll *FROM)
212 ether_ntoa((struct ether_addr *) p + ah->ar_hln + 4)); 207 ether_ntoa((struct ether_addr *) p + ah->ar_hln + 4));
213 } 208 }
214 209
215 if (last.tv_sec) { 210 if (last) {
216 long usecs = (tv.tv_sec - last.tv_sec) * 1000000 + 211 printf(" %u.%03ums\n", last / 1000, last % 1000);
217 tv.tv_usec - last.tv_usec;
218 long msecs = (usecs + 500) / 1000;
219
220 usecs -= msecs * 1000 - 500;
221 printf(" %ld.%03ldms\n", msecs, usecs);
222 } else { 212 } else {
223 printf(" UNSOLICITED?\n"); 213 printf(" UNSOLICITED?\n");
224 } 214 }
@@ -229,11 +219,11 @@ static int recv_pack(unsigned char *buf, int len, struct sockaddr_ll *FROM)
229 brd_recv++; 219 brd_recv++;
230 if (ah->ar_op == htons(ARPOP_REQUEST)) 220 if (ah->ar_op == htons(ARPOP_REQUEST))
231 req_recv++; 221 req_recv++;
232 if (cfg & quit_on_reply) 222 if (cfg & QUIT_ON_REPLY)
233 finish(); 223 finish();
234 if (!(cfg & broadcast_only)) { 224 if (!(cfg & BCAST_ONLY)) {
235 memcpy(he.sll_addr, p, me.sll_halen); 225 memcpy(he.sll_addr, p, me.sll_halen);
236 cfg |= unicasting; 226 cfg |= UNICASTING;
237 } 227 }
238 return 1; 228 return 1;
239} 229}
@@ -245,6 +235,7 @@ int arping_main(int argc, char **argv)
245 int ifindex; 235 int ifindex;
246 char *source = NULL; 236 char *source = NULL;
247 char *target; 237 char *target;
238 unsigned char *packet;
248 239
249 s = xsocket(PF_PACKET, SOCK_DGRAM, 0); 240 s = xsocket(PF_PACKET, SOCK_DGRAM, 0);
250 241
@@ -258,28 +249,23 @@ int arping_main(int argc, char **argv)
258 /* Dad also sets quit_on_reply. 249 /* Dad also sets quit_on_reply.
259 * Advert also sets unsolicited. 250 * Advert also sets unsolicited.
260 */ 251 */
261 opt_complementary = "Df:AU"; 252 opt_complementary = "=1:Df:AU";
262 opt = getopt32(argc, argv, "DUAqfbc:w:I:s:", 253 opt = getopt32(argc, argv, "DUAqfbc:w:I:s:",
263 &_count, &_timeout, &device, &source); 254 &_count, &_timeout, &device, &source);
264 cfg |= opt & 0x3f; /* set respective flags */ 255 cfg |= opt & 0x3f; /* set respective flags */
265 if (opt & 0x40) /* -c: count */ 256 if (opt & 0x40) /* -c: count */
266 count = xatou(_count); 257 count = xatou(_count);
267 if (opt & 0x80) /* -w: timeout */ 258 if (opt & 0x80) /* -w: timeout */
268 timeout = xatoul_range(_timeout, 0, INT_MAX/2000); 259 timeout_us = xatou_range(_timeout, 0, INT_MAX/2000000) * 1000000;
269 //if (opt & 0x100) /* -i: interface */ 260 //if (opt & 0x100) /* -I: interface */
270 if (strlen(device) > IF_NAMESIZE) { 261 if (strlen(device) >= IF_NAMESIZE) {
271 bb_error_msg_and_die("interface name '%s' is too long", 262 bb_error_msg_and_die("interface name '%s' is too long",
272 device); 263 device);
273 } 264 }
274 //if (opt & 0x200) /* -s: source */ 265 //if (opt & 0x200) /* -s: source */
275 } 266 }
276 argc -= optind;
277 argv += optind;
278
279 if (argc != 1)
280 bb_show_usage();
281 267
282 target = *argv; 268 target = argv[optind];
283 269
284 xfunc_error_retval = 2; 270 xfunc_error_retval = 2;
285 271
@@ -301,7 +287,7 @@ int arping_main(int argc, char **argv)
301 } 287 }
302 if (ifr.ifr_flags & (IFF_NOARP | IFF_LOOPBACK)) { 288 if (ifr.ifr_flags & (IFF_NOARP | IFF_LOOPBACK)) {
303 bb_error_msg("interface %s is not ARPable", device); 289 bb_error_msg("interface %s is not ARPable", device);
304 return (cfg & dad ? 0 : 2); 290 return (cfg & DAD ? 0 : 2);
305 } 291 }
306 } 292 }
307 293
@@ -317,10 +303,10 @@ int arping_main(int argc, char **argv)
317 bb_error_msg_and_die("invalid source address %s", source); 303 bb_error_msg_and_die("invalid source address %s", source);
318 } 304 }
319 305
320 if (!(cfg & dad) && (cfg & unsolicited) && src.s_addr == 0) 306 if (!(cfg & DAD) && (cfg & UNSOLICITED) && src.s_addr == 0)
321 src = dst; 307 src = dst;
322 308
323 if (!(cfg & dad) || src.s_addr) { 309 if (!(cfg & DAD) || src.s_addr) {
324 struct sockaddr_in saddr; 310 struct sockaddr_in saddr;
325 int probe_fd = xsocket(AF_INET, SOCK_DGRAM, 0); 311 int probe_fd = xsocket(AF_INET, SOCK_DGRAM, 0);
326 312
@@ -333,7 +319,7 @@ int arping_main(int argc, char **argv)
333 if (src.s_addr) { 319 if (src.s_addr) {
334 saddr.sin_addr = src; 320 saddr.sin_addr = src;
335 xbind(probe_fd, (struct sockaddr *) &saddr, sizeof(saddr)); 321 xbind(probe_fd, (struct sockaddr *) &saddr, sizeof(saddr));
336 } else if (!(cfg & dad)) { 322 } else if (!(cfg & DAD)) {
337 socklen_t alen = sizeof(saddr); 323 socklen_t alen = sizeof(saddr);
338 324
339 saddr.sin_port = htons(1025); 325 saddr.sin_port = htons(1025);
@@ -364,18 +350,18 @@ int arping_main(int argc, char **argv)
364 } 350 }
365 if (me.sll_halen == 0) { 351 if (me.sll_halen == 0) {
366 bb_error_msg("interface \"%s\" is not ARPable (no ll address)", device); 352 bb_error_msg("interface \"%s\" is not ARPable (no ll address)", device);
367 return (cfg & dad ? 0 : 2); 353 return (cfg & DAD ? 0 : 2);
368 } 354 }
369 he = me; 355 he = me;
370 memset(he.sll_addr, -1, he.sll_halen); 356 memset(he.sll_addr, -1, he.sll_halen);
371 357
372 if (!(cfg & quiet)) { 358 if (!(cfg & QUIET)) {
373 printf("ARPING to %s from %s via %s\n", 359 printf("ARPING to %s from %s via %s\n",
374 inet_ntoa(dst), inet_ntoa(src), 360 inet_ntoa(dst), inet_ntoa(src),
375 device ? device : "unknown"); 361 device ? device : "unknown");
376 } 362 }
377 363
378 if (!src.s_addr && !(cfg & dad)) { 364 if (!src.s_addr && !(cfg & DAD)) {
379 bb_error_msg_and_die("no src address in the non-DAD mode"); 365 bb_error_msg_and_die("no src address in the non-DAD mode");
380 } 366 }
381 367
@@ -394,9 +380,9 @@ int arping_main(int argc, char **argv)
394 380
395 catcher(); 381 catcher();
396 382
383 packet = xmalloc(4096);
397 while (1) { 384 while (1) {
398 sigset_t sset, osset; 385 sigset_t sset, osset;
399 RESERVE_CONFIG_UBUFFER(packet, 4096);
400 struct sockaddr_ll from; 386 struct sockaddr_ll from;
401 socklen_t alen = sizeof(from); 387 socklen_t alen = sizeof(from);
402 int cc; 388 int cc;
@@ -412,6 +398,5 @@ int arping_main(int argc, char **argv)
412 sigprocmask(SIG_BLOCK, &sset, &osset); 398 sigprocmask(SIG_BLOCK, &sset, &osset);
413 recv_pack(packet, cc, &from); 399 recv_pack(packet, cc, &from);
414 sigprocmask(SIG_SETMASK, &osset, NULL); 400 sigprocmask(SIG_SETMASK, &osset, NULL);
415 RELEASE_CONFIG_BUFFER(packet);
416 } 401 }
417} 402}