00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <sys/ioctl.h>
00024 #include <sys/signal.h>
00025 #include <sys/time.h>
00026 #include <errno.h>
00027 #include <stdio.h>
00028 #include <stdlib.h>
00029 #include <string.h>
00030 #include <unistd.h>
00031 #include <time.h>
00032 #include <arpa/inet.h>
00033 #include <net/if.h>
00034 #include <netinet/ether.h>
00035 #include <netpacket/packet.h>
00036
00037 #include "arping.h"
00038
00039 static struct in_addr src;
00040 static struct in_addr dst;
00041 static struct sockaddr_ll me;
00042 static struct sockaddr_ll he;
00043 static int32_t s;
00044
00045 static int32_t send_pack(int32_t sock, struct in_addr *src_addr,
00046 struct in_addr *dst_addr, struct sockaddr_ll *ME,
00047 struct sockaddr_ll *HE)
00048 {
00049 int32_t err;
00050 uint8_t buf[256];
00051 struct arphdr *ah = (struct arphdr *) buf;
00052 uint8_t *p = (uint8_t *) (ah + 1);
00053
00054 ah->ar_hrd = htons(ME->sll_hatype);
00055 ah->ar_hrd = htons(ARPHRD_ETHER);
00056 ah->ar_pro = htons(ETH_P_IP);
00057 ah->ar_hln = ME->sll_halen;
00058 ah->ar_pln = 4;
00059 ah->ar_op = htons(ARPOP_REQUEST);
00060
00061 memcpy(p, &ME->sll_addr, ah->ar_hln);
00062 p += ME->sll_halen;
00063
00064 memcpy(p, src_addr, 4);
00065 p += 4;
00066
00067 memcpy(p, &HE->sll_addr, ah->ar_hln);
00068 p += ah->ar_hln;
00069
00070 memcpy(p, dst_addr, 4);
00071 p += 4;
00072
00073 err = sendto(sock, buf, p - buf, 0, (struct sockaddr *) HE, sizeof(*HE));
00074 return err;
00075 }
00076
00077
00078 int32_t recv_pack(uint8_t * buf, int32_t len, struct sockaddr_ll * FROM,
00079 uint8_t * mac)
00080 {
00081 struct arphdr *ah = (struct arphdr *) buf;
00082 uint8_t *p = (uint8_t *) (ah + 1);
00083 struct in_addr src_ip, dst_ip;
00084
00085
00086 if (FROM->sll_pkttype != PACKET_HOST &&
00087 FROM->sll_pkttype != PACKET_BROADCAST &&
00088 FROM->sll_pkttype != PACKET_MULTICAST)
00089 return 0;
00090
00091
00092 if (ah->ar_op != htons(ARPOP_REQUEST)
00093 && ah->ar_op != htons(ARPOP_REPLY))
00094 return 0;
00095
00096
00097 if (ah->ar_hrd != htons(FROM->sll_hatype) &&
00098 (FROM->sll_hatype != ARPHRD_FDDI
00099 || ah->ar_hrd != htons(ARPHRD_ETHER)))
00100 return 0;
00101
00102
00103 if (ah->ar_pro != htons(ETH_P_IP))
00104 return 0;
00105 if (ah->ar_pln != 4)
00106 return 0;
00107 if (ah->ar_hln != me.sll_halen)
00108 return 0;
00109 if (len < sizeof(*ah) + 2 * (4 + ah->ar_hln))
00110 return 0;
00111 memcpy(&src_ip, p + ah->ar_hln, 4);
00112 memcpy(&dst_ip, p + ah->ar_hln + 4 + ah->ar_hln, 4);
00113
00114 if (src_ip.s_addr != dst.s_addr)
00115 return 0;
00116 if (src.s_addr != dst_ip.s_addr)
00117 return 0;
00118 if (memcmp(p + ah->ar_hln + 4, &me.sll_addr, ah->ar_hln))
00119 return 0;
00120
00121 memcpy(mac, p, 6);
00122
00123 return 1;
00124 }
00125
00126 int32_t arping(struct in_addr _src, struct in_addr _dst, uint8_t * mac)
00127 {
00128 int32_t socket_errno;
00129 int32_t ifindex = 0;
00130 int8_t *device = "eth0";
00131
00132 dst = _dst;
00133 src = _src;
00134
00135 s = socket(PF_PACKET, SOCK_DGRAM, 0);
00136 socket_errno = errno;
00137
00138 if (s < 0) {
00139 fprintf(stderr, "socket");
00140 return -1;
00141 }
00142
00143 {
00144 struct ifreq ifr;
00145
00146 memset(&ifr, 0, sizeof(ifr));
00147 strncpy(ifr.ifr_name, device, IFNAMSIZ - 1);
00148 if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) {
00149 fprintf(stderr, "Interface %s not found", device);
00150 return -1;
00151 }
00152 ifindex = ifr.ifr_ifindex;
00153
00154 if (ioctl(s, SIOCGIFFLAGS, (int8_t *) & ifr)) {
00155 fprintf(stderr, "SIOCGIFFLAGS");
00156 return -1;
00157 }
00158 if (!(ifr.ifr_flags & IFF_UP)) {
00159 fprintf(stderr, "Interface %s is down", device);
00160 return -1;
00161 }
00162 if (ifr.ifr_flags & (IFF_NOARP | IFF_LOOPBACK)) {
00163 fprintf(stderr, "Interface %s is not ARPable\n", device);
00164 return -1;
00165 }
00166 }
00167
00168 me.sll_family = AF_PACKET;
00169 me.sll_ifindex = ifindex;
00170 me.sll_protocol = htons(ETH_P_ARP);
00171 if (bind(s, (struct sockaddr *) &me, sizeof(me)) == -1) {
00172 fprintf(stderr, "Error: bind\n");
00173 return -1;
00174 }
00175
00176 {
00177 int32_t alen = sizeof(me);
00178
00179 if (getsockname(s, (struct sockaddr *) &me, &alen) == -1) {
00180 fprintf(stderr, "Error: getsockname\n");
00181 return -1;
00182 }
00183 }
00184
00185 if (me.sll_halen == 0) {
00186 fprintf(stderr,
00187 "Interface \"%s\" is not ARPable (no ll address)\n",
00188 device);
00189 return -1;
00190 }
00191 he = me;
00192 memset(he.sll_addr, -1, he.sll_halen);
00193
00194 {
00195 int8_t packet[4096];
00196 struct sockaddr_ll from;
00197 int32_t alen = sizeof(from);
00198 int32_t cc = 0, res;
00199 struct timeval tm;
00200 int32_t timeout = 3;
00201 time_t prevTime;
00202 fd_set fdset;
00203
00204 tm.tv_usec = 0;
00205 time(&prevTime);
00206
00207 send_pack(s, &src, &dst, &me, &he);
00208
00209 while (timeout > 0) {
00210 FD_ZERO(&fdset);
00211 FD_SET(s, &fdset);
00212 tm.tv_sec = timeout;
00213 res =
00214 select(s + 1, &fdset, (fd_set *) NULL, (fd_set *) NULL,
00215 &tm);
00216 if (res < 0) {
00217 fprintf(stderr, "Error: select\n");
00218 return -1;
00219 }
00220 if (res == 0) {
00221 fprintf(stderr, "Error: host not responded\n");
00222 return -1;
00223 }
00224
00225 if (FD_ISSET(s, &fdset)) {
00226 if ((cc = recvfrom(s, packet, sizeof(packet), 0,
00227 (struct sockaddr *) &from,
00228 &alen)) < 0) {
00229 fprintf(stderr, "Error: recvfrom\n");
00230 return -1;
00231 } else {
00232 break;
00233 }
00234 }
00235 timeout -= time(NULL) - prevTime;
00236 time(&prevTime);
00237 }
00238
00239 res = recv_pack(packet, cc, &from, mac);
00240 if (res != 1)
00241 return -1;
00242 }
00243
00244 return 0;
00245 }
00246