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