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