arping.c 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. /* arping - send ARP REQUEST to a neighbour host.
  2. *
  3. * Copyright 2013 Sandeep Sharma <sandeep.jack2756@gmail.com>
  4. * Copyright 2013 Kyungwan Han <asura321@gmail.com>
  5. *
  6. * No Standard.
  7. USE_ARPING(NEWTOY(arping, "<1>1s:I:w#<0c#<0AUDbqf[+AU][+Df]", TOYFLAG_USR|TOYFLAG_SBIN))
  8. config ARPING
  9. bool "arping"
  10. default n
  11. help
  12. usage: arping [-fqbDUA] [-c CNT] [-w TIMEOUT] [-I IFACE] [-s SRC_IP] DST_IP
  13. Send ARP requests/replies
  14. -f Quit on first ARP reply
  15. -q Quiet
  16. -b Keep broadcasting, don't go unicast
  17. -D Duplicated address detection mode
  18. -U Unsolicited ARP mode, update your neighbors
  19. -A ARP answer mode, update your neighbors
  20. -c N Stop after sending N ARP requests
  21. -w TIMEOUT Time to wait for ARP reply, seconds
  22. -I IFACE Interface to use (default eth0)
  23. -s SRC_IP Sender IP address
  24. DST_IP Target IP address
  25. */
  26. #define FOR_arping
  27. #include "toys.h"
  28. #include <netinet/ether.h>
  29. #include <netpacket/packet.h>
  30. GLOBALS(
  31. long count;
  32. unsigned long time_out;
  33. char *iface;
  34. char *src_ip;
  35. int sockfd;
  36. unsigned long start, end;
  37. unsigned sent_at, sent_nr, rcvd_nr, brd_sent, rcvd_req, brd_rcv,
  38. unicast_flag;
  39. )
  40. struct sockaddr_ll src_pk, dst_pk;
  41. struct in_addr src_addr, dest_addr;
  42. extern void *mempcpy(void *dest, const void *src, size_t n);
  43. // Gets information of INTERFACE and updates IFINDEX, MAC and IP.
  44. static void get_interface(char *interface, int *ifindex, uint32_t *oip,
  45. uint8_t *mac)
  46. {
  47. struct ifreq req;
  48. struct sockaddr_in *ip;
  49. int fd = xsocket(AF_INET, SOCK_RAW, IPPROTO_RAW);
  50. req.ifr_addr.sa_family = AF_INET;
  51. xstrncpy(req.ifr_name, interface, IFNAMSIZ);
  52. req.ifr_name[IFNAMSIZ-1] = '\0';
  53. xioctl(fd, SIOCGIFFLAGS, &req);
  54. if (!(req.ifr_flags & IFF_UP)) return;
  55. if (oip) {
  56. xioctl(fd, SIOCGIFADDR, &req);
  57. ip = (struct sockaddr_in*) &req.ifr_addr;
  58. *oip = ntohl(ip->sin_addr.s_addr);
  59. }
  60. if (ifindex) {
  61. xioctl(fd, SIOCGIFINDEX, &req);
  62. *ifindex = req.ifr_ifindex;
  63. }
  64. if (mac) {
  65. xioctl(fd, SIOCGIFHWADDR, &req);
  66. memcpy(mac, req.ifr_hwaddr.sa_data, 6);
  67. }
  68. xclose(fd);
  69. }
  70. // SIGINT handler, Print Number of Packets send or receive details.
  71. static void done(int sig)
  72. {
  73. if (!(toys.optflags & FLAG_q)) {
  74. xprintf("Sent %u probe(s) (%u broadcast(s))\n", TT.sent_nr, TT.brd_sent);
  75. xprintf("Received %u repl%s (%u request(s), %u broadcast(s))\n",
  76. TT.rcvd_nr, TT.rcvd_nr == 1 ? "y":"ies", TT.rcvd_req, TT.brd_rcv);
  77. }
  78. if (toys.optflags & FLAG_D) exit(!!TT.rcvd_nr);
  79. //In -U mode, No reply is expected.
  80. if (toys.optflags & FLAG_U) exit(EXIT_SUCCESS);
  81. exit(!TT.rcvd_nr);
  82. }
  83. // Create and Send Packet
  84. static void send_packet()
  85. {
  86. int ret;
  87. unsigned char sbuf[256] = {0,};
  88. struct arphdr *arp_h = (struct arphdr *) sbuf;
  89. unsigned char *ptr = (unsigned char *)(arp_h + 1);
  90. arp_h->ar_hrd = htons(ARPHRD_ETHER);
  91. arp_h->ar_pro = htons(ETH_P_IP);
  92. arp_h->ar_hln = src_pk.sll_halen;
  93. arp_h->ar_pln = 4;
  94. arp_h->ar_op = (toys.optflags & FLAG_A) ? htons(ARPOP_REPLY)
  95. : htons(ARPOP_REQUEST);
  96. ptr = mempcpy(ptr, &src_pk.sll_addr, src_pk.sll_halen);
  97. ptr = mempcpy(ptr, &src_addr, 4);
  98. ptr = mempcpy(ptr,
  99. (toys.optflags & FLAG_A) ? &src_pk.sll_addr : &dst_pk.sll_addr,
  100. src_pk.sll_halen);
  101. ptr = mempcpy(ptr, &dest_addr, 4);
  102. ret = sendto(TT.sockfd, sbuf, ptr - sbuf, 0,
  103. (struct sockaddr *)&dst_pk, sizeof(dst_pk));
  104. if (ret == ptr - sbuf) {
  105. struct timeval tval;
  106. gettimeofday(&tval, NULL);
  107. TT.sent_at = tval.tv_sec * 1000000ULL + tval.tv_usec;
  108. TT.sent_nr++;
  109. if (!TT.unicast_flag) TT.brd_sent++;
  110. }
  111. }
  112. // Receive Packet and filter with valid checks.
  113. static void recv_from(struct sockaddr_ll *from, int *recv_len)
  114. {
  115. struct in_addr s_ip, d_ip;
  116. struct arphdr *arp_hdr = (struct arphdr *)toybuf;
  117. unsigned char *p = (unsigned char *)(arp_hdr + 1);
  118. if (arp_hdr->ar_op != htons(ARPOP_REQUEST) &&
  119. arp_hdr->ar_op != htons(ARPOP_REPLY)) return;
  120. if (from->sll_pkttype != PACKET_HOST && from->sll_pkttype != PACKET_BROADCAST
  121. && from->sll_pkttype != PACKET_MULTICAST) return;
  122. if (arp_hdr->ar_pro != htons(ETH_P_IP) || (arp_hdr->ar_pln != 4)
  123. || (arp_hdr->ar_hln != src_pk.sll_halen)
  124. || (*recv_len < (int)(sizeof(*arp_hdr) + 2 * (4 + arp_hdr->ar_hln))))
  125. return;
  126. memcpy(&s_ip.s_addr, p + arp_hdr->ar_hln, 4);
  127. memcpy(&d_ip.s_addr, p + arp_hdr->ar_hln + 4 + arp_hdr->ar_hln, 4);
  128. if (dest_addr.s_addr != s_ip.s_addr) return;
  129. if (toys.optflags & FLAG_D) {
  130. if (src_addr.s_addr && src_addr.s_addr != d_ip.s_addr) return;
  131. if (!memcmp(p, &src_pk.sll_addr, src_pk.sll_halen)) return;
  132. } else if (src_addr.s_addr != d_ip.s_addr ) return;
  133. if (!(toys.optflags & FLAG_q)) {
  134. printf("%scast re%s from %s [%s]",
  135. from->sll_pkttype == PACKET_HOST ? "Uni" : "Broad",
  136. arp_hdr->ar_op == htons(ARPOP_REPLY) ? "ply" : "quest",
  137. inet_ntoa(s_ip), ether_ntoa((struct ether_addr *) p));
  138. if (TT.sent_at) {
  139. unsigned delta;
  140. struct timeval tval;
  141. gettimeofday(&tval, NULL);
  142. delta = (tval.tv_sec * 1000000ULL + (tval.tv_usec)) - TT.sent_at;
  143. xprintf(" %u.%03ums\n", delta / 1000, delta % 1000);
  144. }
  145. }
  146. TT.rcvd_nr++;
  147. if (from->sll_pkttype != PACKET_HOST) TT.brd_rcv++;
  148. if (arp_hdr->ar_op == htons(ARPOP_REQUEST)) TT.rcvd_req++;
  149. if (toys.optflags & FLAG_f) done(0);
  150. if (!(toys.optflags & FLAG_b)) {
  151. memcpy(dst_pk.sll_addr, p, src_pk.sll_halen);
  152. TT.unicast_flag = 1;
  153. }
  154. }
  155. // Alarm signal Handle, send packets in one second interval.
  156. static void send_signal(int sig)
  157. {
  158. struct timeval start;
  159. gettimeofday(&start, NULL);
  160. if (!TT.start)
  161. TT.end = TT.start = start.tv_sec * 1000 + start.tv_usec / 1000;
  162. else TT.end = start.tv_sec*1000 + start.tv_usec / 1000;
  163. if (toys.optflags & FLAG_c) {
  164. if (!TT.count) done(0);
  165. TT.count--;
  166. }
  167. if ((toys.optflags & FLAG_w) && ((TT.end - TT.start) >
  168. ((TT.time_out)*1000))) done(0);
  169. send_packet();
  170. alarm(1);
  171. }
  172. void arping_main(void)
  173. {
  174. struct ifreq ifr;
  175. struct sockaddr_ll from;
  176. socklen_t len;
  177. int if_index, recv_len;
  178. if (!(toys.optflags & FLAG_I)) TT.iface = "eth0";
  179. TT.sockfd = xsocket(AF_PACKET, SOCK_DGRAM, 0);
  180. memset(&ifr, 0, sizeof(ifr));
  181. xstrncpy(ifr.ifr_name, TT.iface, IFNAMSIZ);
  182. get_interface(TT.iface, &if_index, NULL, NULL);
  183. src_pk.sll_ifindex = if_index;
  184. xioctl(TT.sockfd, SIOCGIFFLAGS, (char*)&ifr);
  185. if (!(ifr.ifr_flags & IFF_UP) && !(toys.optflags & FLAG_q))
  186. error_exit("Interface \"%s\" is down", TT.iface);
  187. if ((ifr.ifr_flags & (IFF_NOARP | IFF_LOOPBACK))
  188. && !(toys.optflags & FLAG_q)) {
  189. xprintf("Interface \"%s\" is not ARPable\n", TT.iface);
  190. toys.exitval = (toys.optflags & FLAG_D) ? 0 : 2;
  191. return;
  192. }
  193. if (!inet_aton(*toys.optargs, &dest_addr)) {
  194. struct hostent *hp = gethostbyname2(*toys.optargs, AF_INET);
  195. if (!hp) perror_exit("bad address '%s'", *toys.optargs);
  196. memcpy(&dest_addr, hp->h_addr, 4);
  197. }
  198. if ((toys.optflags & FLAG_s) && !(inet_aton(TT.src_ip, &src_addr)))
  199. perror_exit("invalid source address '%s'",TT.src_ip);
  200. if (!(toys.optflags & FLAG_D) && (toys.optflags & FLAG_U)
  201. && !src_addr.s_addr) src_addr = dest_addr;
  202. if (!(toys.optflags & FLAG_D) || src_addr.s_addr) {
  203. struct sockaddr_in saddr;
  204. int p_fd = xsocket(AF_INET, SOCK_DGRAM, 0);
  205. if (setsockopt(p_fd, SOL_SOCKET, SO_BINDTODEVICE, TT.iface,
  206. strlen(TT.iface))) perror_exit("setsockopt");
  207. memset(&saddr, 0, sizeof(saddr));
  208. saddr.sin_family = AF_INET;
  209. if (src_addr.s_addr) {
  210. saddr.sin_addr = src_addr;
  211. xbind(p_fd, (struct sockaddr*)&saddr, sizeof(saddr));
  212. } else {
  213. uint32_t oip;
  214. saddr.sin_port = htons(1025);
  215. saddr.sin_addr = dest_addr;
  216. xconnect(p_fd, (struct sockaddr *) &saddr, sizeof(saddr));
  217. get_interface(TT.iface, NULL, &oip, NULL);
  218. src_addr.s_addr = htonl(oip);
  219. }
  220. xclose(p_fd);
  221. }
  222. src_pk.sll_family = AF_PACKET;
  223. src_pk.sll_protocol = htons(ETH_P_ARP);
  224. xbind(TT.sockfd, (struct sockaddr *)&src_pk, sizeof(src_pk));
  225. socklen_t alen = sizeof(src_pk);
  226. getsockname(TT.sockfd, (struct sockaddr *)&src_pk, &alen);
  227. if (!src_pk.sll_halen) {
  228. perror_msg("src is not arpable");
  229. toys.exitval = (toys.optflags & FLAG_D) ? 0 : 2;
  230. return;
  231. }
  232. if (!(toys.optflags & FLAG_q)) {
  233. xprintf("ARPING to %s", inet_ntoa(dest_addr));
  234. xprintf(" from %s via %s\n", inet_ntoa(src_addr), TT.iface);
  235. }
  236. dst_pk = src_pk;
  237. //First packet always broadcasts.
  238. memset(dst_pk.sll_addr, -1, dst_pk.sll_halen);
  239. signal(SIGINT, done);
  240. signal(SIGALRM, send_signal);
  241. send_signal(0); // Send first Broadcast message.
  242. while (1) {
  243. len = sizeof(from);
  244. recv_len = recvfrom(TT.sockfd, toybuf, 4096, 0,
  245. (struct sockaddr *)&from, &len);
  246. if (recv_len < 0) continue;
  247. recv_from(&from, &recv_len);
  248. }
  249. }