aboutsummaryrefslogtreecommitdiff
path: root/networking/arping.c
diff options
context:
space:
mode:
Diffstat (limited to 'networking/arping.c')
-rw-r--r--networking/arping.c83
1 files changed, 41 insertions, 42 deletions
diff --git a/networking/arping.c b/networking/arping.c
index a022e70ea..7a9fbc2f4 100644
--- a/networking/arping.c
+++ b/networking/arping.c
@@ -33,18 +33,17 @@ enum {
33 BCAST_ONLY = 32, 33 BCAST_ONLY = 32,
34 UNICASTING = 64 34 UNICASTING = 64
35}; 35};
36static int cfg;
37 36
38static int s; 37static int sock;
39static unsigned count = UINT_MAX; 38static unsigned count = UINT_MAX;
40static unsigned timeout_us; 39static unsigned timeout_us;
41static int sent; 40static unsigned sent;
42static int brd_sent; 41static unsigned brd_sent;
43static int received; 42static unsigned received;
44static int brd_recv; 43static unsigned brd_recv;
45static int req_recv; 44static unsigned req_recv;
46 45
47static int send_pack(int sock, struct in_addr *src_addr, 46static int send_pack(struct in_addr *src_addr,
48 struct in_addr *dst_addr, struct sockaddr_ll *ME, 47 struct in_addr *dst_addr, struct sockaddr_ll *ME,
49 struct sockaddr_ll *HE) 48 struct sockaddr_ll *HE)
50{ 49{
@@ -59,7 +58,7 @@ static int send_pack(int sock, struct in_addr *src_addr,
59 ah->ar_pro = htons(ETH_P_IP); 58 ah->ar_pro = htons(ETH_P_IP);
60 ah->ar_hln = ME->sll_halen; 59 ah->ar_hln = ME->sll_halen;
61 ah->ar_pln = 4; 60 ah->ar_pln = 4;
62 ah->ar_op = cfg & ADVERT ? htons(ARPOP_REPLY) : htons(ARPOP_REQUEST); 61 ah->ar_op = option_mask32 & ADVERT ? htons(ARPOP_REPLY) : htons(ARPOP_REQUEST);
63 62
64 memcpy(p, &ME->sll_addr, ah->ar_hln); 63 memcpy(p, &ME->sll_addr, ah->ar_hln);
65 p += ME->sll_halen; 64 p += ME->sll_halen;
@@ -67,7 +66,7 @@ static int send_pack(int sock, struct in_addr *src_addr,
67 memcpy(p, src_addr, 4); 66 memcpy(p, src_addr, 4);
68 p += 4; 67 p += 4;
69 68
70 if (cfg & ADVERT) 69 if (option_mask32 & ADVERT)
71 memcpy(p, &ME->sll_addr, ah->ar_hln); 70 memcpy(p, &ME->sll_addr, ah->ar_hln);
72 else 71 else
73 memcpy(p, &HE->sll_addr, ah->ar_hln); 72 memcpy(p, &HE->sll_addr, ah->ar_hln);
@@ -81,7 +80,7 @@ static int send_pack(int sock, struct in_addr *src_addr,
81 if (err == p - buf) { 80 if (err == p - buf) {
82 last = now; 81 last = now;
83 sent++; 82 sent++;
84 if (!(cfg & UNICASTING)) 83 if (!(option_mask32 & UNICASTING))
85 brd_sent++; 84 brd_sent++;
86 } 85 }
87 return err; 86 return err;
@@ -90,17 +89,17 @@ static int send_pack(int sock, struct in_addr *src_addr,
90static void finish(void) ATTRIBUTE_NORETURN; 89static void finish(void) ATTRIBUTE_NORETURN;
91static void finish(void) 90static void finish(void)
92{ 91{
93 if (!(cfg & QUIET)) { 92 if (!(option_mask32 & QUIET)) {
94 printf("Sent %d probe(s) (%d broadcast(s))\n" 93 printf("Sent %u probe(s) (%u broadcast(s))\n"
95 "Received %d repl%s" 94 "Received %u repl%s"
96 " (%d request(s), %d broadcast(s))\n", 95 " (%u request(s), %u broadcast(s))\n",
97 sent, brd_sent, 96 sent, brd_sent,
98 received, (received == 1) ? "ies" : "y", 97 received, (received == 1) ? "ies" : "y",
99 req_recv, brd_recv); 98 req_recv, brd_recv);
100 } 99 }
101 if (cfg & DAD) 100 if (option_mask32 & DAD)
102 exit(!!received); 101 exit(!!received);
103 if (cfg & UNSOLICITED) 102 if (option_mask32 & UNSOLICITED)
104 exit(0); 103 exit(0);
105 exit(!received); 104 exit(!received);
106} 105}
@@ -121,8 +120,8 @@ static void catcher(void)
121 count--; 120 count--;
122 121
123 if (last == 0 || (now - last) > 500000) { 122 if (last == 0 || (now - last) > 500000) {
124 send_pack(s, &src, &dst, &me, &he); 123 send_pack(&src, &dst, &me, &he);
125 if (count == 0 && (cfg & UNSOLICITED)) 124 if (count == 0 && (option_mask32 & UNSOLICITED))
126 finish(); 125 finish();
127 } 126 }
128 alarm(1); 127 alarm(1);
@@ -160,7 +159,7 @@ static int recv_pack(unsigned char *buf, int len, struct sockaddr_ll *FROM)
160 return 0; 159 return 0;
161 memcpy(&src_ip, p + ah->ar_hln, 4); 160 memcpy(&src_ip, p + ah->ar_hln, 4);
162 memcpy(&dst_ip, p + ah->ar_hln + 4 + ah->ar_hln, 4); 161 memcpy(&dst_ip, p + ah->ar_hln + 4 + ah->ar_hln, 4);
163 if (!(cfg & DAD)) { 162 if (!(option_mask32 & DAD)) {
164 if (src_ip.s_addr != dst.s_addr) 163 if (src_ip.s_addr != dst.s_addr)
165 return 0; 164 return 0;
166 if (src.s_addr != dst_ip.s_addr) 165 if (src.s_addr != dst_ip.s_addr)
@@ -188,7 +187,7 @@ static int recv_pack(unsigned char *buf, int len, struct sockaddr_ll *FROM)
188 if (src.s_addr && src.s_addr != dst_ip.s_addr) 187 if (src.s_addr && src.s_addr != dst_ip.s_addr)
189 return 0; 188 return 0;
190 } 189 }
191 if (!(cfg & QUIET)) { 190 if (!(option_mask32 & QUIET)) {
192 int s_printed = 0; 191 int s_printed = 0;
193 192
194 printf("%scast re%s from %s [%s]", 193 printf("%scast re%s from %s [%s]",
@@ -219,11 +218,11 @@ static int recv_pack(unsigned char *buf, int len, struct sockaddr_ll *FROM)
219 brd_recv++; 218 brd_recv++;
220 if (ah->ar_op == htons(ARPOP_REQUEST)) 219 if (ah->ar_op == htons(ARPOP_REQUEST))
221 req_recv++; 220 req_recv++;
222 if (cfg & QUIT_ON_REPLY) 221 if (option_mask32 & QUIT_ON_REPLY)
223 finish(); 222 finish();
224 if (!(cfg & BCAST_ONLY)) { 223 if (!(option_mask32 & BCAST_ONLY)) {
225 memcpy(he.sll_addr, p, me.sll_halen); 224 memcpy(he.sll_addr, p, me.sll_halen);
226 cfg |= UNICASTING; 225 option_mask32 |= UNICASTING;
227 } 226 }
228 return 1; 227 return 1;
229} 228}
@@ -237,32 +236,32 @@ int arping_main(int argc, char **argv)
237 char *target; 236 char *target;
238 unsigned char *packet; 237 unsigned char *packet;
239 238
240 s = xsocket(PF_PACKET, SOCK_DGRAM, 0); 239 sock = xsocket(PF_PACKET, SOCK_DGRAM, 0);
241 240
242 // Drop suid root privileges 241 // Drop suid root privileges
243 xsetuid(getuid()); 242 xsetuid(getuid());
244 243
245 { 244 {
246 unsigned opt; 245 unsigned opt;
247 char *_count, *_timeout; 246 char *str_count, *str_timeout;
248 247
249 /* Dad also sets quit_on_reply. 248 /* Dad also sets quit_on_reply.
250 * Advert also sets unsolicited. 249 * Advert also sets unsolicited.
251 */ 250 */
252 opt_complementary = "=1:Df:AU"; 251 opt_complementary = "=1:Df:AU";
253 opt = getopt32(argc, argv, "DUAqfbc:w:I:s:", 252 opt = getopt32(argc, argv, "DUAqfbc:w:I:s:",
254 &_count, &_timeout, &device, &source); 253 &str_count, &str_timeout, &device, &source);
255 cfg |= opt & 0x3f; /* set respective flags */
256 if (opt & 0x40) /* -c: count */ 254 if (opt & 0x40) /* -c: count */
257 count = xatou(_count); 255 count = xatou(str_count);
258 if (opt & 0x80) /* -w: timeout */ 256 if (opt & 0x80) /* -w: timeout */
259 timeout_us = xatou_range(_timeout, 0, INT_MAX/2000000) * 1000000; 257 timeout_us = xatou_range(str_timeout, 0, INT_MAX/2000000) * 1000000;
260 //if (opt & 0x100) /* -I: interface */ 258 //if (opt & 0x100) /* -I: interface */
261 if (strlen(device) >= IF_NAMESIZE) { 259 if (strlen(device) >= IF_NAMESIZE) {
262 bb_error_msg_and_die("interface name '%s' is too long", 260 bb_error_msg_and_die("interface name '%s' is too long",
263 device); 261 device);
264 } 262 }
265 //if (opt & 0x200) /* -s: source */ 263 //if (opt & 0x200) /* -s: source */
264 option_mask32 &= 0x3f; /* set respective flags */
266 } 265 }
267 266
268 target = argv[optind]; 267 target = argv[optind];
@@ -274,12 +273,12 @@ int arping_main(int argc, char **argv)
274 273
275 memset(&ifr, 0, sizeof(ifr)); 274 memset(&ifr, 0, sizeof(ifr));
276 strncpy(ifr.ifr_name, device, IFNAMSIZ - 1); 275 strncpy(ifr.ifr_name, device, IFNAMSIZ - 1);
277 if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) { 276 if (ioctl(sock, SIOCGIFINDEX, &ifr) < 0) {
278 bb_error_msg_and_die("interface %s not found", device); 277 bb_error_msg_and_die("interface %s not found", device);
279 } 278 }
280 ifindex = ifr.ifr_ifindex; 279 ifindex = ifr.ifr_ifindex;
281 280
282 if (ioctl(s, SIOCGIFFLAGS, (char *) &ifr)) { 281 if (ioctl(sock, SIOCGIFFLAGS, (char *) &ifr)) {
283 bb_error_msg_and_die("SIOCGIFFLAGS"); 282 bb_error_msg_and_die("SIOCGIFFLAGS");
284 } 283 }
285 if (!(ifr.ifr_flags & IFF_UP)) { 284 if (!(ifr.ifr_flags & IFF_UP)) {
@@ -287,7 +286,7 @@ int arping_main(int argc, char **argv)
287 } 286 }
288 if (ifr.ifr_flags & (IFF_NOARP | IFF_LOOPBACK)) { 287 if (ifr.ifr_flags & (IFF_NOARP | IFF_LOOPBACK)) {
289 bb_error_msg("interface %s is not ARPable", device); 288 bb_error_msg("interface %s is not ARPable", device);
290 return (cfg & DAD ? 0 : 2); 289 return (option_mask32 & DAD ? 0 : 2);
291 } 290 }
292 } 291 }
293 292
@@ -303,10 +302,10 @@ int arping_main(int argc, char **argv)
303 bb_error_msg_and_die("invalid source address %s", source); 302 bb_error_msg_and_die("invalid source address %s", source);
304 } 303 }
305 304
306 if (!(cfg & DAD) && (cfg & UNSOLICITED) && src.s_addr == 0) 305 if (!(option_mask32 & DAD) && (option_mask32 & UNSOLICITED) && src.s_addr == 0)
307 src = dst; 306 src = dst;
308 307
309 if (!(cfg & DAD) || src.s_addr) { 308 if (!(option_mask32 & DAD) || src.s_addr) {
310 struct sockaddr_in saddr; 309 struct sockaddr_in saddr;
311 int probe_fd = xsocket(AF_INET, SOCK_DGRAM, 0); 310 int probe_fd = xsocket(AF_INET, SOCK_DGRAM, 0);
312 311
@@ -319,7 +318,7 @@ int arping_main(int argc, char **argv)
319 if (src.s_addr) { 318 if (src.s_addr) {
320 saddr.sin_addr = src; 319 saddr.sin_addr = src;
321 xbind(probe_fd, (struct sockaddr *) &saddr, sizeof(saddr)); 320 xbind(probe_fd, (struct sockaddr *) &saddr, sizeof(saddr));
322 } else if (!(cfg & DAD)) { 321 } else if (!(option_mask32 & DAD)) {
323 socklen_t alen = sizeof(saddr); 322 socklen_t alen = sizeof(saddr);
324 323
325 saddr.sin_port = htons(1025); 324 saddr.sin_port = htons(1025);
@@ -339,29 +338,29 @@ int arping_main(int argc, char **argv)
339 me.sll_family = AF_PACKET; 338 me.sll_family = AF_PACKET;
340 me.sll_ifindex = ifindex; 339 me.sll_ifindex = ifindex;
341 me.sll_protocol = htons(ETH_P_ARP); 340 me.sll_protocol = htons(ETH_P_ARP);
342 xbind(s, (struct sockaddr *) &me, sizeof(me)); 341 xbind(sock, (struct sockaddr *) &me, sizeof(me));
343 342
344 { 343 {
345 socklen_t alen = sizeof(me); 344 socklen_t alen = sizeof(me);
346 345
347 if (getsockname(s, (struct sockaddr *) &me, &alen) == -1) { 346 if (getsockname(sock, (struct sockaddr *) &me, &alen) == -1) {
348 bb_error_msg_and_die("getsockname"); 347 bb_error_msg_and_die("getsockname");
349 } 348 }
350 } 349 }
351 if (me.sll_halen == 0) { 350 if (me.sll_halen == 0) {
352 bb_error_msg("interface \"%s\" is not ARPable (no ll address)", device); 351 bb_error_msg("interface \"%s\" is not ARPable (no ll address)", device);
353 return (cfg & DAD ? 0 : 2); 352 return (option_mask32 & DAD ? 0 : 2);
354 } 353 }
355 he = me; 354 he = me;
356 memset(he.sll_addr, -1, he.sll_halen); 355 memset(he.sll_addr, -1, he.sll_halen);
357 356
358 if (!(cfg & QUIET)) { 357 if (!(option_mask32 & QUIET)) {
359 printf("ARPING to %s from %s via %s\n", 358 printf("ARPING to %s from %s via %s\n",
360 inet_ntoa(dst), inet_ntoa(src), 359 inet_ntoa(dst), inet_ntoa(src),
361 device ? device : "unknown"); 360 device ? device : "unknown");
362 } 361 }
363 362
364 if (!src.s_addr && !(cfg & DAD)) { 363 if (!src.s_addr && !(option_mask32 & DAD)) {
365 bb_error_msg_and_die("no src address in the non-DAD mode"); 364 bb_error_msg_and_die("no src address in the non-DAD mode");
366 } 365 }
367 366
@@ -387,7 +386,7 @@ int arping_main(int argc, char **argv)
387 socklen_t alen = sizeof(from); 386 socklen_t alen = sizeof(from);
388 int cc; 387 int cc;
389 388
390 cc = recvfrom(s, packet, 4096, 0, (struct sockaddr *) &from, &alen); 389 cc = recvfrom(sock, packet, 4096, 0, (struct sockaddr *) &from, &alen);
391 if (cc < 0) { 390 if (cc < 0) {
392 bb_perror_msg("recvfrom"); 391 bb_perror_msg("recvfrom");
393 continue; 392 continue;