blob: ee99b926d8c4d4eb1bdd102da34759825070695d [file] [log] [blame]
Jeremy Kerr42dc98c2016-02-25 10:23:14 +08001/******************************************************************************
2* Copyright 2016 Foxconn
3*
4* Licensed under the Apache License, Version 2.0 (the "License");
5* you may not use this file except in compliance with the License.
6* You may obtain a copy of the License at
7*
8* http://www.apache.org/licenses/LICENSE-2.0
9*
10* Unless required by applicable law or agreed to in writing, software
11* distributed under the License is distributed on an "AS IS" BASIS,
12* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13* See the License for the specific language governing permissions and
14* limitations under the License.
15******************************************************************************/
Jeremy Kerr982b7bc2016-02-25 10:54:39 +080016
17#include <stdio.h>
18#include <stdlib.h>
19#include <string.h>
20#include <errno.h>
21#include <time.h>
22#include <unistd.h>
23
24#include <sys/ioctl.h>
25#include <sys/socket.h>
26
27#include <netinet/in.h>
Jeremy Kerr760d6ac2016-02-25 14:45:33 +080028#include <arpa/inet.h>
Jeremy Kerr982b7bc2016-02-25 10:54:39 +080029
30#include <linux/if_packet.h>
31#include <linux/if_ether.h>
32#include <linux/if_arp.h>
33
Jeremy Kerr66a28052016-02-25 14:31:35 +080034#define ETH_ARP_FRAME_LEN ( \
35 sizeof(struct ethhdr) + \
36 sizeof(struct arphdr) + \
Jeremy Kerr760d6ac2016-02-25 14:45:33 +080037 ((ETH_ALEN + sizeof(struct in_addr)) * 2))
Jeremy Kerr42dc98c2016-02-25 10:23:14 +080038
Jeremy Kerr760d6ac2016-02-25 14:45:33 +080039struct arp_packet {
Jeremy Kerr42dc98c2016-02-25 10:23:14 +080040 struct ethhdr eh;
41 struct arphdr arp;
Jeremy Kerr760d6ac2016-02-25 14:45:33 +080042 uint8_t src_mac[ETH_ALEN];
43 struct in_addr src_ip;
44 uint8_t dest_mac[ETH_ALEN];
45 struct in_addr dest_ip;
46} __attribute__((packed));
Jeremy Kerr42dc98c2016-02-25 10:23:14 +080047
Jeremy Kerr7b3bcf72016-02-25 14:29:55 +080048static int send_arp_packet(int fd,
Jeremy Kerr5514f7b2016-02-25 12:41:44 +080049 int ifindex,
Jeremy Kerr760d6ac2016-02-25 14:45:33 +080050 struct arp_packet *eth_arp,
Jeremy Kerr5514f7b2016-02-25 12:41:44 +080051 __be16 ar_op,
52 unsigned char *src_mac,
Jeremy Kerr760d6ac2016-02-25 14:45:33 +080053 struct in_addr *src_ip,
54 unsigned char *dest_mac,
55 struct in_addr *dest_ip)
Jeremy Kerr42dc98c2016-02-25 10:23:14 +080056{
57 int send_result = 0;
58 struct ethhdr *eh = &eth_arp->eh;
59 struct arphdr *arp = &eth_arp->arp;
Jeremy Kerr42dc98c2016-02-25 10:23:14 +080060 struct sockaddr_ll socket_address;
Jeremy Kerrc10bedb2016-02-25 14:26:38 +080061
62 /* Prepare our link-layer address: raw packet interface,
63 * using the ifindex interface, receiving ARP packets
64 */
Jeremy Kerr5514f7b2016-02-25 12:41:44 +080065 socket_address.sll_family = PF_PACKET;
Jeremy Kerr42dc98c2016-02-25 10:23:14 +080066 socket_address.sll_protocol = htons(ETH_P_ARP);
Jeremy Kerr5514f7b2016-02-25 12:41:44 +080067 socket_address.sll_ifindex = ifindex;
Jeremy Kerr5514f7b2016-02-25 12:41:44 +080068 socket_address.sll_hatype = ARPHRD_ETHER;
Jeremy Kerr5514f7b2016-02-25 12:41:44 +080069 socket_address.sll_pkttype = PACKET_OTHERHOST;
Jeremy Kerr5514f7b2016-02-25 12:41:44 +080070 socket_address.sll_halen = ETH_ALEN;
Jeremy Kerr42dc98c2016-02-25 10:23:14 +080071 memcpy(socket_address.sll_addr, dest_mac, ETH_ALEN);
Jeremy Kerrc10bedb2016-02-25 14:26:38 +080072
73 /* set the frame header */
Jeremy Kerr5514f7b2016-02-25 12:41:44 +080074 memcpy((void *)eh->h_dest, (void *)dest_mac, ETH_ALEN);
75 memcpy((void *)eh->h_source, (void *)src_mac, ETH_ALEN);
Jeremy Kerr42dc98c2016-02-25 10:23:14 +080076 eh->h_proto = htons(ETH_P_ARP);
Jeremy Kerrc10bedb2016-02-25 14:26:38 +080077
78 /* Fill InARP request data for ethernet + ipv4 */
Jeremy Kerr42dc98c2016-02-25 10:23:14 +080079 arp->ar_hrd = htons(ARPHRD_ETHER);
80 arp->ar_pro = htons(ETH_P_ARP);
81 arp->ar_hln = ETH_ALEN;
82 arp->ar_pln = 4;
Jeremy Kerr5514f7b2016-02-25 12:41:44 +080083 arp->ar_op = htons(ar_op);
Jeremy Kerrc10bedb2016-02-25 14:26:38 +080084
85 /* fill arp ethernet mac & ipv4 info */
Jeremy Kerr760d6ac2016-02-25 14:45:33 +080086 memcpy(&eth_arp->src_mac, src_mac, sizeof(eth_arp->src_mac));
87 memcpy(&eth_arp->src_ip, src_ip, sizeof(eth_arp->src_ip));
88 memcpy(&eth_arp->dest_mac, dest_mac, sizeof(eth_arp->dest_mac));
89 memcpy(&eth_arp->dest_ip, dest_ip, sizeof(eth_arp->dest_ip));
Jeremy Kerrc10bedb2016-02-25 14:26:38 +080090
91 /* send the packet */
Jeremy Kerr5514f7b2016-02-25 12:41:44 +080092 send_result = sendto(fd, eth_arp, ETH_ARP_FRAME_LEN, 0,
93 (struct sockaddr *)&socket_address,
94 sizeof(socket_address));
Jeremy Kerr42dc98c2016-02-25 10:23:14 +080095 if (send_result == -1) {
Jeremy Kerr5514f7b2016-02-25 12:41:44 +080096 printf("sendto: [%s]\n", strerror(errno));
Jeremy Kerr42dc98c2016-02-25 10:23:14 +080097 }
98 return send_result;
99}
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800100
Jeremy Kerr7b3bcf72016-02-25 14:29:55 +0800101static void show_mac_addr(const char *name, unsigned char *mac_addr)
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800102{
103 int i;
104 printf("%s MAC address: ", name);
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800105 for (i = 0; i < 6; i++) {
106 printf("%.2X%c", (unsigned char)mac_addr[i],
107 (i == 5) ? '\n' : ':');
108 }
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800109 return;
110}
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800111
Jeremy Kerr115522d2016-02-25 10:24:14 +0800112static void usage(const char *progname)
113{
114 fprintf(stderr, "Usage: %s <interface>\n", progname);
115}
116
117int main(int argc, char **argv)
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800118{
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800119 /*buffer for ethernet frame */
Jeremy Kerrc10bedb2016-02-25 14:26:38 +0800120 static unsigned char buffer[ETH_FRAME_LEN];
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800121 int send_result = 0;
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800122 static struct ifreq ifreq_buffer;
Jeremy Kerr115522d2016-02-25 10:24:14 +0800123 const char *ifname;
Jeremy Kerr760d6ac2016-02-25 14:45:33 +0800124 int fd, ret;
Jeremy Kerr115522d2016-02-25 10:24:14 +0800125
126 if (argc < 2) {
127 usage(argv[0]);
128 return EXIT_FAILURE;
129 }
130
131 ifname = argv[1];
132
133 if (strlen(ifname) > IFNAMSIZ) {
134 fprintf(stderr, "Interface name '%s' is invalid\n", ifname);
135 return EXIT_FAILURE;
136 }
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800137
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800138 static unsigned char src_mac[6];
Jeremy Kerr760d6ac2016-02-25 14:45:33 +0800139 static struct in_addr src_ip;
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800140 int ifindex;
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800141
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800142 if (((fd = socket(AF_PACKET, SOCK_PACKET, htons(ETH_P_ARP)))) == -1) {
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800143 printf("socket: [%s]\n", strerror(errno));
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800144 exit(-1);
145 }
Jeremy Kerrc10bedb2016-02-25 14:26:38 +0800146
147 /* Query local mac address */
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800148 memset(&ifreq_buffer, 0x00, sizeof(ifreq_buffer));
Jeremy Kerr115522d2016-02-25 10:24:14 +0800149 strcpy(ifreq_buffer.ifr_name, ifname);
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800150 ret = ioctl(fd, SIOCGIFHWADDR, &ifreq_buffer);
151 if (ret == -1) {
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800152 printf("ioctl2: [%s]\n", strerror(errno));
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800153 close(fd);
154 exit(-1);
155 }
156 memcpy(src_mac, ifreq_buffer.ifr_hwaddr.sa_data, ETH_ALEN);
Jeremy Kerr115522d2016-02-25 10:24:14 +0800157 show_mac_addr(ifname, src_mac);
Jeremy Kerrc10bedb2016-02-25 14:26:38 +0800158
159 /* find the ifindex of the interface we're using */
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800160 memset(&ifreq_buffer, 0x00, sizeof(ifreq_buffer));
Jeremy Kerr115522d2016-02-25 10:24:14 +0800161 strcpy(ifreq_buffer.ifr_name, ifname);
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800162 ret = ioctl(fd, SIOCGIFINDEX, &ifreq_buffer);
163 if (ret == -1) {
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800164 printf("ioctl4: [%s]\n", strerror(errno));
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800165 close(fd);
166 exit(-1);
167 }
168 ifindex = ifreq_buffer.ifr_ifindex;
169
Jeremy Kerrc10bedb2016-02-25 14:26:38 +0800170 /* length of the received frame */
171 int length = 0;
Jeremy Kerr760d6ac2016-02-25 14:45:33 +0800172 static struct arp_packet *inarp_req = (void *)buffer;
173 static struct arp_packet inarp_resp;
Jeremy Kerrc10bedb2016-02-25 14:26:38 +0800174
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800175 while (1) {
Jeremy Kerrc10bedb2016-02-25 14:26:38 +0800176 /* get local ip address */
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800177 memset(&ifreq_buffer, 0x00, sizeof(ifreq_buffer));
Jeremy Kerr115522d2016-02-25 10:24:14 +0800178 strcpy(ifreq_buffer.ifr_name, ifname);
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800179 ret = ioctl(fd, SIOCGIFADDR, &ifreq_buffer);
180 if (ret == -1) {
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800181 sleep(1);
182 continue;
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800183 }
184
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800185 if (AF_INET == ifreq_buffer.ifr_addr.sa_family) {
Jeremy Kerr760d6ac2016-02-25 14:45:33 +0800186 memcpy(&src_ip, &ifreq_buffer.ifr_addr.sa_data[2],
187 sizeof(src_ip));
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800188 } else {
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800189 printf("unknown address family [%d]!\n",
190 ifreq_buffer.ifr_addr.sa_family);
191 sleep(1);
192 continue;
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800193 }
194
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800195 memset((void *)&inarp_resp, 0, sizeof inarp_resp);
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800196 length = recvfrom(fd, buffer, ETH_ARP_FRAME_LEN, 0, NULL, NULL);
197 if (length == -1) {
198 sleep(1);
199 }
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800200 if (0 == memcmp(src_mac, inarp_req->eh.h_dest, ETH_ALEN)) {
Jeremy Kerrc10bedb2016-02-25 14:26:38 +0800201 if (ntohs(inarp_req->arp.ar_op) == ARPOP_InREQUEST) {
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800202
203 printf
204 ("src mac =%02x:%02x:%02x:%02x:%02x:%02x\r\n",
Jeremy Kerr760d6ac2016-02-25 14:45:33 +0800205 inarp_req->src_mac[0],
206 inarp_req->src_mac[1],
207 inarp_req->src_mac[2],
208 inarp_req->src_mac[3],
209 inarp_req->src_mac[4],
210 inarp_req->src_mac[5]
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800211 );
Jeremy Kerr760d6ac2016-02-25 14:45:33 +0800212 printf("src ip = %s\r\n",
213 inet_ntoa(inarp_req->src_ip));
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800214 int fd_1;
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800215 if (((fd_1 =
216 socket(AF_PACKET, SOCK_RAW, 0))) == -1) {
217 printf("socket: [%s]\n",
218 strerror(errno));
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800219 exit(-1);
220 }
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800221 send_result =
222 send_arp_packet(fd_1, ifindex, &inarp_resp,
223 ARPOP_InREPLY,
Jeremy Kerr760d6ac2016-02-25 14:45:33 +0800224 inarp_req->dest_mac,
225 &src_ip,
226 inarp_req->src_mac,
227 &inarp_req->src_ip);
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800228 close(fd_1);
229 if (send_result == -1) {
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800230 printf("[Rsp] sendto: [%s]\n",
231 strerror(errno));
232 sleep(1);
233 continue;
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800234 }
235 }
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800236 memset(buffer, 0, sizeof(buffer));
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800237 }
238 }
239 close(fd);
240 return 0;
241}