3
0

arping.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499
  1. /*
  2. * arping.c - Ping hosts by ARP requests/replies
  3. *
  4. * This program is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License
  6. * as published by the Free Software Foundation; either version
  7. * 2 of the License, or (at your option) any later version.
  8. *
  9. * Author: Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
  10. * Busybox port: Nick Fedchik <nick@fedchik.org.ua>
  11. */
  12. #include <sys/ioctl.h>
  13. #include <sys/signal.h>
  14. #include <sys/time.h>
  15. #include <errno.h>
  16. #include <stdlib.h>
  17. #include <string.h>
  18. #include <unistd.h>
  19. #include <arpa/inet.h>
  20. #include <net/if.h>
  21. #include <netinet/ether.h>
  22. #include <netpacket/packet.h>
  23. #include "busybox.h"
  24. #define APPLET_NAME "arping"
  25. static struct in_addr src;
  26. static struct in_addr dst;
  27. static struct sockaddr_ll me;
  28. static struct sockaddr_ll he;
  29. static struct timeval last;
  30. static int dad;
  31. static int unsolicited;
  32. static int advert;
  33. static int quiet;
  34. static int quit_on_reply = 0;
  35. static int count = -1;
  36. static int timeout;
  37. static int unicasting;
  38. static int s;
  39. static int broadcast_only;
  40. static int sent;
  41. static int brd_sent;
  42. static int received;
  43. static int brd_recv;
  44. static int req_recv;
  45. #define MS_TDIFF(tv1,tv2) ( ((tv1).tv_sec-(tv2).tv_sec)*1000 + \
  46. ((tv1).tv_usec-(tv2).tv_usec)/1000 )
  47. #if 0
  48. static void set_signal(int signo, void (*handler) (void))
  49. {
  50. struct sigaction sa;
  51. memset(&sa, 0, sizeof(sa));
  52. sa.sa_handler = (void (*)(int)) handler;
  53. sa.sa_flags = SA_RESTART;
  54. sigaction(signo, &sa, NULL);
  55. }
  56. #endif
  57. static int send_pack(int sock, struct in_addr *src_addr,
  58. struct in_addr *dst_addr, struct sockaddr_ll *ME,
  59. struct sockaddr_ll *HE)
  60. {
  61. int err;
  62. struct timeval now;
  63. unsigned char buf[256];
  64. struct arphdr *ah = (struct arphdr *) buf;
  65. unsigned char *p = (unsigned char *) (ah + 1);
  66. ah->ar_hrd = htons(ME->sll_hatype);
  67. ah->ar_hrd = htons(ARPHRD_ETHER);
  68. ah->ar_pro = htons(ETH_P_IP);
  69. ah->ar_hln = ME->sll_halen;
  70. ah->ar_pln = 4;
  71. ah->ar_op = advert ? htons(ARPOP_REPLY) : htons(ARPOP_REQUEST);
  72. memcpy(p, &ME->sll_addr, ah->ar_hln);
  73. p += ME->sll_halen;
  74. memcpy(p, src_addr, 4);
  75. p += 4;
  76. if (advert)
  77. memcpy(p, &ME->sll_addr, ah->ar_hln);
  78. else
  79. memcpy(p, &HE->sll_addr, ah->ar_hln);
  80. p += ah->ar_hln;
  81. memcpy(p, dst_addr, 4);
  82. p += 4;
  83. gettimeofday(&now, NULL);
  84. err = sendto(sock, buf, p - buf, 0, (struct sockaddr *) HE, sizeof(*HE));
  85. if (err == p - buf) {
  86. last = now;
  87. sent++;
  88. if (!unicasting)
  89. brd_sent++;
  90. }
  91. return err;
  92. }
  93. static void finish(void)
  94. {
  95. if (!quiet) {
  96. printf("Sent %d probes (%d broadcast(s))\n", sent, brd_sent);
  97. printf("Received %d repl%s", received, (received > 1) ? "ies" : "y");
  98. if (brd_recv || req_recv) {
  99. printf(" (");
  100. if (req_recv)
  101. printf("%d request(s)", req_recv);
  102. if (brd_recv)
  103. printf("%s%d broadcast(s)", req_recv ? ", " : "", brd_recv);
  104. putchar(')');
  105. }
  106. putchar('\n');
  107. fflush(stdout);
  108. }
  109. if (dad)
  110. exit(!!received);
  111. if (unsolicited)
  112. exit(0);
  113. exit(!received);
  114. }
  115. static void catcher(void)
  116. {
  117. struct timeval tv;
  118. static struct timeval start;
  119. gettimeofday(&tv, NULL);
  120. if (start.tv_sec == 0)
  121. start = tv;
  122. if (count-- == 0
  123. || (timeout && MS_TDIFF(tv, start) > timeout * 1000 + 500))
  124. finish();
  125. if (last.tv_sec == 0 || MS_TDIFF(tv, last) > 500) {
  126. send_pack(s, &src, &dst, &me, &he);
  127. if (count == 0 && unsolicited)
  128. finish();
  129. }
  130. alarm(1);
  131. }
  132. static int recv_pack(unsigned char *buf, int len, struct sockaddr_ll *FROM)
  133. {
  134. struct timeval tv;
  135. struct arphdr *ah = (struct arphdr *) buf;
  136. unsigned char *p = (unsigned char *) (ah + 1);
  137. struct in_addr src_ip, dst_ip;
  138. gettimeofday(&tv, NULL);
  139. /* Filter out wild packets */
  140. if (FROM->sll_pkttype != PACKET_HOST &&
  141. FROM->sll_pkttype != PACKET_BROADCAST &&
  142. FROM->sll_pkttype != PACKET_MULTICAST)
  143. return 0;
  144. /* Only these types are recognised */
  145. if (ah->ar_op != htons(ARPOP_REQUEST) && ah->ar_op != htons(ARPOP_REPLY))
  146. return 0;
  147. /* ARPHRD check and this darned FDDI hack here :-( */
  148. if (ah->ar_hrd != htons(FROM->sll_hatype) &&
  149. (FROM->sll_hatype != ARPHRD_FDDI
  150. || ah->ar_hrd != htons(ARPHRD_ETHER)))
  151. return 0;
  152. /* Protocol must be IP. */
  153. if (ah->ar_pro != htons(ETH_P_IP))
  154. return 0;
  155. if (ah->ar_pln != 4)
  156. return 0;
  157. if (ah->ar_hln != me.sll_halen)
  158. return 0;
  159. if (len < sizeof(*ah) + 2 * (4 + ah->ar_hln))
  160. return 0;
  161. memcpy(&src_ip, p + ah->ar_hln, 4);
  162. memcpy(&dst_ip, p + ah->ar_hln + 4 + ah->ar_hln, 4);
  163. if (!dad) {
  164. if (src_ip.s_addr != dst.s_addr)
  165. return 0;
  166. if (src.s_addr != dst_ip.s_addr)
  167. return 0;
  168. if (memcmp(p + ah->ar_hln + 4, &me.sll_addr, ah->ar_hln))
  169. return 0;
  170. } else {
  171. /* DAD packet was:
  172. src_ip = 0 (or some src)
  173. src_hw = ME
  174. dst_ip = tested address
  175. dst_hw = <unspec>
  176. We fail, if receive request/reply with:
  177. src_ip = tested_address
  178. src_hw != ME
  179. if src_ip in request was not zero, check
  180. also that it matches to dst_ip, otherwise
  181. dst_ip/dst_hw do not matter.
  182. */
  183. if (src_ip.s_addr != dst.s_addr)
  184. return 0;
  185. if (memcmp(p, &me.sll_addr, me.sll_halen) == 0)
  186. return 0;
  187. if (src.s_addr && src.s_addr != dst_ip.s_addr)
  188. return 0;
  189. }
  190. if (!quiet) {
  191. int s_printed = 0;
  192. printf("%s ",
  193. FROM->sll_pkttype == PACKET_HOST ? "Unicast" : "Broadcast");
  194. printf("%s from ",
  195. ah->ar_op == htons(ARPOP_REPLY) ? "reply" : "request");
  196. printf("%s ", inet_ntoa(src_ip));
  197. printf("[%s]", ether_ntoa((struct ether_addr *) p));
  198. if (dst_ip.s_addr != src.s_addr) {
  199. printf("for %s ", inet_ntoa(dst_ip));
  200. s_printed = 1;
  201. }
  202. if (memcmp(p + ah->ar_hln + 4, me.sll_addr, ah->ar_hln)) {
  203. if (!s_printed)
  204. printf("for ");
  205. printf("[%s]",
  206. ether_ntoa((struct ether_addr *) p + ah->ar_hln + 4));
  207. }
  208. if (last.tv_sec) {
  209. long usecs = (tv.tv_sec - last.tv_sec) * 1000000 +
  210. tv.tv_usec - last.tv_usec;
  211. long msecs = (usecs + 500) / 1000;
  212. usecs -= msecs * 1000 - 500;
  213. printf(" %ld.%03ldms\n", msecs, usecs);
  214. } else {
  215. printf(" UNSOLICITED?\n");
  216. }
  217. fflush(stdout);
  218. }
  219. received++;
  220. if (FROM->sll_pkttype != PACKET_HOST)
  221. brd_recv++;
  222. if (ah->ar_op == htons(ARPOP_REQUEST))
  223. req_recv++;
  224. if (quit_on_reply)
  225. finish();
  226. if (!broadcast_only) {
  227. memcpy(he.sll_addr, p, me.sll_halen);
  228. unicasting = 1;
  229. }
  230. return 1;
  231. }
  232. int arping_main(int argc, char **argv)
  233. {
  234. int socket_errno;
  235. int ch;
  236. uid_t uid = getuid();
  237. char *device = "eth0";
  238. int ifindex = 0;
  239. char *source = NULL;
  240. char *target;
  241. s = socket(PF_PACKET, SOCK_DGRAM, 0);
  242. socket_errno = errno;
  243. setuid(uid);
  244. while ((ch = getopt(argc, argv, "h?bfDUAqc:w:s:I:")) != EOF) {
  245. switch (ch) {
  246. case 'b':
  247. broadcast_only = 1;
  248. break;
  249. case 'D':
  250. dad++;
  251. quit_on_reply = 1;
  252. break;
  253. case 'U':
  254. unsolicited++;
  255. break;
  256. case 'A':
  257. advert++;
  258. unsolicited++;
  259. break;
  260. case 'q':
  261. quiet++;
  262. break;
  263. case 'c':
  264. count = atoi(optarg);
  265. break;
  266. case 'w':
  267. timeout = atoi(optarg);
  268. break;
  269. case 'I':
  270. if (optarg == NULL)
  271. bb_show_usage();
  272. if (bb_strlen(optarg) > IF_NAMESIZE) {
  273. bb_error_msg("Interface name `%s' must be less than %d", optarg,
  274. IF_NAMESIZE);
  275. exit(2);
  276. }
  277. device = optarg;
  278. break;
  279. case 'f':
  280. quit_on_reply = 1;
  281. break;
  282. case 's':
  283. source = optarg;
  284. break;
  285. case 'h':
  286. case '?':
  287. default:
  288. bb_show_usage();
  289. }
  290. }
  291. argc -= optind;
  292. argv += optind;
  293. if (argc != 1)
  294. bb_show_usage();
  295. target = *argv;
  296. if (s < 0) {
  297. bb_error_msg("socket");
  298. exit(socket_errno);
  299. }
  300. {
  301. struct ifreq ifr;
  302. memset(&ifr, 0, sizeof(ifr));
  303. strncpy(ifr.ifr_name, device, IFNAMSIZ - 1);
  304. if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) {
  305. bb_error_msg("Interface %s not found", device);
  306. exit(2);
  307. }
  308. ifindex = ifr.ifr_ifindex;
  309. if (ioctl(s, SIOCGIFFLAGS, (char *) &ifr)) {
  310. bb_error_msg("SIOCGIFFLAGS");
  311. exit(2);
  312. }
  313. if (!(ifr.ifr_flags & IFF_UP)) {
  314. bb_error_msg("Interface %s is down", device);
  315. exit(2);
  316. }
  317. if (ifr.ifr_flags & (IFF_NOARP | IFF_LOOPBACK)) {
  318. bb_error_msg("Interface %s is not ARPable", device);
  319. exit(dad ? 0 : 2);
  320. }
  321. }
  322. if (!inet_aton(target, &dst)) {
  323. struct hostent *hp;
  324. hp = gethostbyname2(target, AF_INET);
  325. if (!hp) {
  326. bb_error_msg("invalid or unknown target %s", target);
  327. exit(2);
  328. }
  329. memcpy(&dst, hp->h_addr, 4);
  330. }
  331. if (source && !inet_aton(source, &src)) {
  332. bb_error_msg("invalid source address %s", source);
  333. exit(2);
  334. }
  335. if (!dad && unsolicited && src.s_addr == 0)
  336. src = dst;
  337. if (!dad || src.s_addr) {
  338. struct sockaddr_in saddr;
  339. int probe_fd = socket(AF_INET, SOCK_DGRAM, 0);
  340. if (probe_fd < 0) {
  341. bb_error_msg("socket");
  342. exit(2);
  343. }
  344. if (device) {
  345. if (setsockopt
  346. (probe_fd, SOL_SOCKET, SO_BINDTODEVICE, device,
  347. strlen(device) + 1) == -1)
  348. bb_error_msg("WARNING: interface %s is ignored", device);
  349. }
  350. memset(&saddr, 0, sizeof(saddr));
  351. saddr.sin_family = AF_INET;
  352. if (src.s_addr) {
  353. saddr.sin_addr = src;
  354. if (bind(probe_fd, (struct sockaddr *) &saddr, sizeof(saddr)) == -1) {
  355. bb_error_msg("bind");
  356. exit(2);
  357. }
  358. } else if (!dad) {
  359. int on = 1;
  360. int alen = sizeof(saddr);
  361. saddr.sin_port = htons(1025);
  362. saddr.sin_addr = dst;
  363. if (setsockopt
  364. (probe_fd, SOL_SOCKET, SO_DONTROUTE, (char *) &on,
  365. sizeof(on)) == -1)
  366. perror("WARNING: setsockopt(SO_DONTROUTE)");
  367. if (connect(probe_fd, (struct sockaddr *) &saddr, sizeof(saddr))
  368. == -1) {
  369. bb_error_msg("connect");
  370. exit(2);
  371. }
  372. if (getsockname(probe_fd, (struct sockaddr *) &saddr, &alen) ==
  373. -1) {
  374. bb_error_msg("getsockname");
  375. exit(2);
  376. }
  377. src = saddr.sin_addr;
  378. }
  379. close(probe_fd);
  380. };
  381. me.sll_family = AF_PACKET;
  382. me.sll_ifindex = ifindex;
  383. me.sll_protocol = htons(ETH_P_ARP);
  384. if (bind(s, (struct sockaddr *) &me, sizeof(me)) == -1) {
  385. bb_error_msg("bind");
  386. exit(2);
  387. }
  388. {
  389. int alen = sizeof(me);
  390. if (getsockname(s, (struct sockaddr *) &me, &alen) == -1) {
  391. bb_error_msg("getsockname");
  392. exit(2);
  393. }
  394. }
  395. if (me.sll_halen == 0) {
  396. bb_error_msg("Interface \"%s\" is not ARPable (no ll address)", device);
  397. exit(dad ? 0 : 2);
  398. }
  399. he = me;
  400. memset(he.sll_addr, -1, he.sll_halen);
  401. if (!quiet) {
  402. printf("ARPING to %s", inet_ntoa(dst));
  403. printf(" from %s via %s\n", inet_ntoa(src),
  404. device ? device : "unknown");
  405. }
  406. if (!src.s_addr && !dad) {
  407. bb_error_msg("no src address in the non-DAD mode");
  408. exit(2);
  409. }
  410. {
  411. struct sigaction sa;
  412. memset(&sa, 0, sizeof(sa));
  413. sa.sa_flags = SA_RESTART;
  414. sa.sa_handler = (void (*)(int)) finish;
  415. sigaction(SIGINT, &sa, NULL);
  416. sa.sa_handler = (void (*)(int)) catcher;
  417. sigaction(SIGALRM, &sa, NULL);
  418. }
  419. catcher();
  420. while (1) {
  421. sigset_t sset, osset;
  422. char packet[4096];
  423. struct sockaddr_ll from;
  424. int alen = sizeof(from);
  425. int cc;
  426. if ((cc = recvfrom(s, packet, sizeof(packet), 0,
  427. (struct sockaddr *) &from, &alen)) < 0) {
  428. perror("recvfrom");
  429. continue;
  430. }
  431. sigemptyset(&sset);
  432. sigaddset(&sset, SIGALRM);
  433. sigaddset(&sset, SIGINT);
  434. sigprocmask(SIG_BLOCK, &sset, &osset);
  435. recv_pack(packet, cc, &from);
  436. sigprocmask(SIG_SETMASK, &osset, NULL);
  437. }
  438. }