blob: 46a9e9c447ee147b66524c6e38ff1eb20e298ab2 [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>
28
29#include <linux/if_packet.h>
30#include <linux/if_ether.h>
31#include <linux/if_arp.h>
32
Jeremy Kerr42dc98c2016-02-25 10:23:14 +080033#define MAX_SERVER_NODE 24
34#define SKU1_MAX_SERVER_NODES 24
35
36#define ETH_ARP_FRAME_LEN ( sizeof(struct ethhdr)+\
37 sizeof(struct arphdr)+\
38 ((ETH_ALEN+4)*2)\
39 )
40
41struct ARP_DATA {
Jeremy Kerrc10bedb2016-02-25 14:26:38 +080042 unsigned char src_mac[ETH_ALEN];
43 unsigned char src_ip[4];
44 unsigned char dest_mac[ETH_ALEN];
45 unsigned char dest_ip[4];
Jeremy Kerr42dc98c2016-02-25 10:23:14 +080046};
47struct ETH_ARP_PACKET {
48 struct ethhdr eh;
49 struct arphdr arp;
50 struct ARP_DATA arp_data;
51};
52
53struct ETH_ARP_PACKET *inarp_req;
54
Jeremy Kerr5514f7b2016-02-25 12:41:44 +080055static char based_mac[6] = { 0, 0, 0, 0, 0, 0 };
56
Jeremy Kerr42dc98c2016-02-25 10:23:14 +080057int send_arp_packet(int fd,
Jeremy Kerr5514f7b2016-02-25 12:41:44 +080058 int ifindex,
59 struct ETH_ARP_PACKET *eth_arp,
60 __be16 ar_op,
61 unsigned char *src_mac,
62 unsigned char *src_ip,
63 unsigned char *dest_mac, unsigned char *dest_ip)
Jeremy Kerr42dc98c2016-02-25 10:23:14 +080064{
65 int send_result = 0;
66 struct ethhdr *eh = &eth_arp->eh;
67 struct arphdr *arp = &eth_arp->arp;
68 struct ARP_DATA *arp_data = &eth_arp->arp_data;
Jeremy Kerr42dc98c2016-02-25 10:23:14 +080069 struct sockaddr_ll socket_address;
Jeremy Kerrc10bedb2016-02-25 14:26:38 +080070
71 /* Prepare our link-layer address: raw packet interface,
72 * using the ifindex interface, receiving ARP packets
73 */
Jeremy Kerr5514f7b2016-02-25 12:41:44 +080074 socket_address.sll_family = PF_PACKET;
Jeremy Kerr42dc98c2016-02-25 10:23:14 +080075 socket_address.sll_protocol = htons(ETH_P_ARP);
Jeremy Kerr5514f7b2016-02-25 12:41:44 +080076 socket_address.sll_ifindex = ifindex;
Jeremy Kerr5514f7b2016-02-25 12:41:44 +080077 socket_address.sll_hatype = ARPHRD_ETHER;
Jeremy Kerr5514f7b2016-02-25 12:41:44 +080078 socket_address.sll_pkttype = PACKET_OTHERHOST;
Jeremy Kerr5514f7b2016-02-25 12:41:44 +080079 socket_address.sll_halen = ETH_ALEN;
Jeremy Kerr42dc98c2016-02-25 10:23:14 +080080 memcpy(socket_address.sll_addr, dest_mac, ETH_ALEN);
Jeremy Kerrc10bedb2016-02-25 14:26:38 +080081
82 /* set the frame header */
Jeremy Kerr5514f7b2016-02-25 12:41:44 +080083 memcpy((void *)eh->h_dest, (void *)dest_mac, ETH_ALEN);
84 memcpy((void *)eh->h_source, (void *)src_mac, ETH_ALEN);
Jeremy Kerr42dc98c2016-02-25 10:23:14 +080085 eh->h_proto = htons(ETH_P_ARP);
Jeremy Kerrc10bedb2016-02-25 14:26:38 +080086
87 /* Fill InARP request data for ethernet + ipv4 */
Jeremy Kerr42dc98c2016-02-25 10:23:14 +080088 arp->ar_hrd = htons(ARPHRD_ETHER);
89 arp->ar_pro = htons(ETH_P_ARP);
90 arp->ar_hln = ETH_ALEN;
91 arp->ar_pln = 4;
Jeremy Kerr5514f7b2016-02-25 12:41:44 +080092 arp->ar_op = htons(ar_op);
Jeremy Kerrc10bedb2016-02-25 14:26:38 +080093
94 /* fill arp ethernet mac & ipv4 info */
Jeremy Kerr5514f7b2016-02-25 12:41:44 +080095 arp_data = (void *)(arp + 1);
Jeremy Kerrc10bedb2016-02-25 14:26:38 +080096 memcpy(arp_data->src_mac, (void *)src_mac, ETH_ALEN);
97 memcpy(arp_data->src_ip, src_ip, 4);
98 memcpy(arp_data->dest_mac, (void *)dest_mac, ETH_ALEN);
99 memcpy(arp_data->dest_ip, dest_ip, 4);
100
101 /* send the packet */
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800102 send_result = sendto(fd, eth_arp, ETH_ARP_FRAME_LEN, 0,
103 (struct sockaddr *)&socket_address,
104 sizeof(socket_address));
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800105 if (send_result == -1) {
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800106 printf("sendto: [%s]\n", strerror(errno));
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800107 }
108 return send_result;
109}
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800110
Jeremy Kerr115522d2016-02-25 10:24:14 +0800111void show_mac_addr(const char *name, unsigned char *mac_addr)
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800112{
113 int i;
114 printf("%s MAC address: ", name);
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800115 for (i = 0; i < 6; i++) {
116 printf("%.2X%c", (unsigned char)mac_addr[i],
117 (i == 5) ? '\n' : ':');
118 }
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800119 return;
120}
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800121
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800122void show_ip_addr(char *desc, unsigned char *ip_addr)
123{
124 int i;
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800125 printf("%s IPv4 address: ", desc);
126 for (i = 0; i < 4; i++) {
127 printf("%d%c", (unsigned char)ip_addr[i],
128 (i == 3) ? '\n' : '.');
129 }
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800130}
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800131
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800132void dump_data(char *desc, unsigned char *buffer, int length)
133{
134 int i;
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800135 printf("%s & length is [%d]:\n", desc, length);
136 for (i = 0; i < length; i++) {
137 printf("[%02X]", 0xff & buffer[i]);
138 if ((i & 0xf) == 0x7)
139 printf(" - ");
140 if ((i & 0xf) == 0xf)
141 printf("\n");
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800142 }
143 printf("\n");
144}
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800145
146void get_mac_address_for_node_id(int node_id, char *mac_addr)
147{
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800148 int i;
149 int add = node_id;
150 int carry = 0;
151 int mac;
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800152 for (i = 5; i >= 0; i--) {
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800153 mac = (int)based_mac[i];
154 mac += (add + carry);
155 add = 0;
156 if (mac > 255) {
157 carry = 1;
158 mac -= 256;
159 } else {
160 carry = 0;
161 }
162 mac_addr[i] = (char)mac;
163 }
164}
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800165
Jeremy Kerrc10bedb2016-02-25 14:26:38 +0800166/* return node_id or -1 for error */
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800167int get_node_id_by_mac_address(unsigned char *target_mac_addr)
168{
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800169 char mac_addr[ETH_ALEN];
170 int i;
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800171 for (i = 0; i < MAX_SERVER_NODE; i++) {
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800172 get_mac_address_for_node_id(i, mac_addr);
173 if (0 == memcmp(target_mac_addr, mac_addr, ETH_ALEN))
174 break;
175 }
176 if (i != MAX_SERVER_NODE) {
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800177 return i;
178 } else
179 return -1;
180}
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800181
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800182#if ENABLE_MONOTONIC_SYSCALL
183#include <sys/syscall.h>
184/* Old glibc (< 2.3.4) does not provide this constant. We use syscall
185 * directly so this definition is safe. */
186#ifndef CLOCK_MONOTONIC
187#define CLOCK_MONOTONIC 1
188#endif
189
190unsigned FAST_FUNC monotonic_sec(void)
191{
192 struct timespec ts;
193 get_mono(&ts);
194 return ts.tv_sec;
195}
196
197#else
198
199unsigned monotonic_sec(void)
200{
201 return time(NULL);
202}
203#endif
Jeremy Kerr115522d2016-02-25 10:24:14 +0800204
205static void usage(const char *progname)
206{
207 fprintf(stderr, "Usage: %s <interface>\n", progname);
208}
209
210int main(int argc, char **argv)
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800211{
212 int fd, ret;
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800213 /*buffer for ethernet frame */
Jeremy Kerrc10bedb2016-02-25 14:26:38 +0800214 static unsigned char buffer[ETH_FRAME_LEN];
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800215 int send_result = 0;
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800216 static struct ifreq ifreq_buffer;
Jeremy Kerr115522d2016-02-25 10:24:14 +0800217 const char *ifname;
218
219 if (argc < 2) {
220 usage(argv[0]);
221 return EXIT_FAILURE;
222 }
223
224 ifname = argv[1];
225
226 if (strlen(ifname) > IFNAMSIZ) {
227 fprintf(stderr, "Interface name '%s' is invalid\n", ifname);
228 return EXIT_FAILURE;
229 }
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800230
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800231 static unsigned char src_mac[6];
232 static unsigned char src_ip[4];
233 int ifindex;
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800234
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800235 if (((fd = socket(AF_PACKET, SOCK_PACKET, htons(ETH_P_ARP)))) == -1) {
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800236 printf("socket: [%s]\n", strerror(errno));
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800237 exit(-1);
238 }
Jeremy Kerrc10bedb2016-02-25 14:26:38 +0800239
240 /* Query local mac address */
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800241 memset(&ifreq_buffer, 0x00, sizeof(ifreq_buffer));
Jeremy Kerr115522d2016-02-25 10:24:14 +0800242 strcpy(ifreq_buffer.ifr_name, ifname);
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800243 ret = ioctl(fd, SIOCGIFHWADDR, &ifreq_buffer);
244 if (ret == -1) {
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800245 printf("ioctl2: [%s]\n", strerror(errno));
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800246 close(fd);
247 exit(-1);
248 }
249 memcpy(src_mac, ifreq_buffer.ifr_hwaddr.sa_data, ETH_ALEN);
Jeremy Kerr115522d2016-02-25 10:24:14 +0800250 show_mac_addr(ifname, src_mac);
Jeremy Kerrc10bedb2016-02-25 14:26:38 +0800251
252 /* find the ifindex of the interface we're using */
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800253 memset(&ifreq_buffer, 0x00, sizeof(ifreq_buffer));
Jeremy Kerr115522d2016-02-25 10:24:14 +0800254 strcpy(ifreq_buffer.ifr_name, ifname);
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800255 ret = ioctl(fd, SIOCGIFINDEX, &ifreq_buffer);
256 if (ret == -1) {
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800257 printf("ioctl4: [%s]\n", strerror(errno));
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800258 close(fd);
259 exit(-1);
260 }
261 ifindex = ifreq_buffer.ifr_ifindex;
262
Jeremy Kerrc10bedb2016-02-25 14:26:38 +0800263 /* length of the received frame */
264 int length = 0;
265 static struct ETH_ARP_PACKET *inarp_req =
266 (struct ETH_ARP_PACKET *)buffer;
267 static struct ETH_ARP_PACKET inarp_resp;
268
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800269 while (1) {
Jeremy Kerrc10bedb2016-02-25 14:26:38 +0800270 /* get local ip address */
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800271 memset(&ifreq_buffer, 0x00, sizeof(ifreq_buffer));
Jeremy Kerr115522d2016-02-25 10:24:14 +0800272 strcpy(ifreq_buffer.ifr_name, ifname);
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800273 ret = ioctl(fd, SIOCGIFADDR, &ifreq_buffer);
274 if (ret == -1) {
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800275 sleep(1);
276 continue;
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800277 }
278
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800279 if (AF_INET == ifreq_buffer.ifr_addr.sa_family) {
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800280 memcpy(src_ip, &ifreq_buffer.ifr_addr.sa_data[2], 4);
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800281 } else {
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800282 printf("unknown address family [%d]!\n",
283 ifreq_buffer.ifr_addr.sa_family);
284 sleep(1);
285 continue;
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800286 }
287
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800288 memset((void *)&inarp_resp, 0, sizeof inarp_resp);
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800289 length = recvfrom(fd, buffer, ETH_ARP_FRAME_LEN, 0, NULL, NULL);
290 if (length == -1) {
291 sleep(1);
292 }
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800293 if (0 == memcmp(src_mac, inarp_req->eh.h_dest, ETH_ALEN)) {
Jeremy Kerrc10bedb2016-02-25 14:26:38 +0800294 if (ntohs(inarp_req->arp.ar_op) == ARPOP_InREQUEST) {
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800295
296 printf
297 ("src mac =%02x:%02x:%02x:%02x:%02x:%02x\r\n",
298 inarp_req->arp_data.src_mac[0],
299 inarp_req->arp_data.src_mac[1],
300 inarp_req->arp_data.src_mac[2],
301 inarp_req->arp_data.src_mac[3],
302 inarp_req->arp_data.src_mac[4],
303 inarp_req->arp_data.src_mac[5]
304 );
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800305 printf("src ip =%d:%d:%d:%d\r\n",
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800306 inarp_req->arp_data.src_ip[0],
307 inarp_req->arp_data.src_ip[1],
308 inarp_req->arp_data.src_ip[2],
309 inarp_req->arp_data.src_ip[3]
310 );
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800311 int fd_1;
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800312 if (((fd_1 =
313 socket(AF_PACKET, SOCK_RAW, 0))) == -1) {
314 printf("socket: [%s]\n",
315 strerror(errno));
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800316 exit(-1);
317 }
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800318 send_result =
319 send_arp_packet(fd_1, ifindex, &inarp_resp,
320 ARPOP_InREPLY,
321 inarp_req->arp_data.
322 dest_mac, src_ip,
323 inarp_req->arp_data.src_mac,
324 inarp_req->arp_data.src_ip);
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800325 close(fd_1);
326 if (send_result == -1) {
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800327 printf("[Rsp] sendto: [%s]\n",
328 strerror(errno));
329 sleep(1);
330 continue;
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800331 }
332 }
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800333 memset(buffer, 0, sizeof(buffer));
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800334 }
335 }
336 close(fd);
337 return 0;
338}