blob: 7a7124716e1bf18710a957903c0f181526dfc24c [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 Kerr5514f7b2016-02-25 12:41:44 +080042 unsigned char src_mac[ETH_ALEN]; //source mac addr
43 unsigned char src_ip[4]; //source ip addr
44 unsigned char dest_mac[ETH_ALEN]; //dest mac addr
45 unsigned char dest_ip[4]; //dest ip
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 Kerr5514f7b2016-02-25 12:41:44 +080069 /*target address */
Jeremy Kerr42dc98c2016-02-25 10:23:14 +080070 struct sockaddr_ll socket_address;
Jeremy Kerr5514f7b2016-02-25 12:41:44 +080071 /*prepare sockaddr_ll */
72 /*RAW communication */
73 socket_address.sll_family = PF_PACKET;
Jeremy Kerr42dc98c2016-02-25 10:23:14 +080074 /*we don't use a protocoll above ethernet layer
Jeremy Kerr5514f7b2016-02-25 12:41:44 +080075 ->just use anything here */
Jeremy Kerr42dc98c2016-02-25 10:23:14 +080076 socket_address.sll_protocol = htons(ETH_P_ARP);
77 /*index of the network device
Jeremy Kerr5514f7b2016-02-25 12:41:44 +080078 see full code later how to retrieve it */
79 socket_address.sll_ifindex = ifindex;
80 /*ARP hardware identifier is ethernet */
81 socket_address.sll_hatype = ARPHRD_ETHER;
82 /*target is another host */
83 socket_address.sll_pkttype = PACKET_OTHERHOST;
84 /*address length */
85 socket_address.sll_halen = ETH_ALEN;
Jeremy Kerr42dc98c2016-02-25 10:23:14 +080086 memcpy(socket_address.sll_addr, dest_mac, ETH_ALEN);
Jeremy Kerr5514f7b2016-02-25 12:41:44 +080087 /*set the frame header */
88 memcpy((void *)eh->h_dest, (void *)dest_mac, ETH_ALEN);
89 memcpy((void *)eh->h_source, (void *)src_mac, ETH_ALEN);
Jeremy Kerr42dc98c2016-02-25 10:23:14 +080090 eh->h_proto = htons(ETH_P_ARP);
Jeremy Kerr5514f7b2016-02-25 12:41:44 +080091 /*fill InARP request data for ethernet + ipv4 */
Jeremy Kerr42dc98c2016-02-25 10:23:14 +080092 arp->ar_hrd = htons(ARPHRD_ETHER);
93 arp->ar_pro = htons(ETH_P_ARP);
94 arp->ar_hln = ETH_ALEN;
95 arp->ar_pln = 4;
Jeremy Kerr5514f7b2016-02-25 12:41:44 +080096 arp->ar_op = htons(ar_op);
Jeremy Kerr42dc98c2016-02-25 10:23:14 +080097 //fill arp ethernet mac & ipv4 info
Jeremy Kerr5514f7b2016-02-25 12:41:44 +080098 arp_data = (void *)(arp + 1);
99 memcpy(arp_data->src_mac, (void *)src_mac, ETH_ALEN); //source mac addr
100 memcpy(arp_data->src_ip, src_ip, 4); //source ip addr
101 memcpy(arp_data->dest_mac, (void *)dest_mac, ETH_ALEN); //dest mac addr
102 memcpy(arp_data->dest_ip, dest_ip, 4); //dest ip
103 /*send the packet */
104 send_result = sendto(fd, eth_arp, ETH_ARP_FRAME_LEN, 0,
105 (struct sockaddr *)&socket_address,
106 sizeof(socket_address));
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800107 if (send_result == -1) {
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800108 printf("sendto: [%s]\n", strerror(errno));
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800109 }
110 return send_result;
111}
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800112
Jeremy Kerr115522d2016-02-25 10:24:14 +0800113void show_mac_addr(const char *name, unsigned char *mac_addr)
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800114{
115 int i;
116 printf("%s MAC address: ", name);
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800117 for (i = 0; i < 6; i++) {
118 printf("%.2X%c", (unsigned char)mac_addr[i],
119 (i == 5) ? '\n' : ':');
120 }
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800121 return;
122}
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800123
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800124void show_ip_addr(char *desc, unsigned char *ip_addr)
125{
126 int i;
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800127 printf("%s IPv4 address: ", desc);
128 for (i = 0; i < 4; i++) {
129 printf("%d%c", (unsigned char)ip_addr[i],
130 (i == 3) ? '\n' : '.');
131 }
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800132}
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800133
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800134void dump_data(char *desc, unsigned char *buffer, int length)
135{
136 int i;
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800137 printf("%s & length is [%d]:\n", desc, length);
138 for (i = 0; i < length; i++) {
139 printf("[%02X]", 0xff & buffer[i]);
140 if ((i & 0xf) == 0x7)
141 printf(" - ");
142 if ((i & 0xf) == 0xf)
143 printf("\n");
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800144 }
145 printf("\n");
146}
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800147
148void get_mac_address_for_node_id(int node_id, char *mac_addr)
149{
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800150 int i;
151 int add = node_id;
152 int carry = 0;
153 int mac;
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800154 for (i = 5; i >= 0; i--) {
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800155 mac = (int)based_mac[i];
156 mac += (add + carry);
157 add = 0;
158 if (mac > 255) {
159 carry = 1;
160 mac -= 256;
161 } else {
162 carry = 0;
163 }
164 mac_addr[i] = (char)mac;
165 }
166}
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800167
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800168//return node_id or -1 for error
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800169int get_node_id_by_mac_address(unsigned char *target_mac_addr)
170{
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800171 char mac_addr[ETH_ALEN];
172 int i;
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800173 for (i = 0; i < MAX_SERVER_NODE; i++) {
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800174 get_mac_address_for_node_id(i, mac_addr);
175 if (0 == memcmp(target_mac_addr, mac_addr, ETH_ALEN))
176 break;
177 }
178 if (i != MAX_SERVER_NODE) {
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800179// int j;
180// printf("mac_address for node[%d]:", i+1);
181// for (j=0; j<6; j++)
182// printf("%02x:", 0xff & mac_addr[j]);
183// printf("\n");
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800184 return i;
185 } else
186 return -1;
187}
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800188
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800189#if ENABLE_MONOTONIC_SYSCALL
190#include <sys/syscall.h>
191/* Old glibc (< 2.3.4) does not provide this constant. We use syscall
192 * directly so this definition is safe. */
193#ifndef CLOCK_MONOTONIC
194#define CLOCK_MONOTONIC 1
195#endif
196
197unsigned FAST_FUNC monotonic_sec(void)
198{
199 struct timespec ts;
200 get_mono(&ts);
201 return ts.tv_sec;
202}
203
204#else
205
206unsigned monotonic_sec(void)
207{
208 return time(NULL);
209}
210#endif
Jeremy Kerr115522d2016-02-25 10:24:14 +0800211
212static void usage(const char *progname)
213{
214 fprintf(stderr, "Usage: %s <interface>\n", progname);
215}
216
217int main(int argc, char **argv)
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800218{
219 int fd, ret;
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800220 /*buffer for ethernet frame */
221 static unsigned char buffer[ETH_FRAME_LEN]; /* single packets are usually not bigger than 8192 bytes */
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800222 int send_result = 0;
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800223 static struct ifreq ifreq_buffer;
Jeremy Kerr115522d2016-02-25 10:24:14 +0800224 const char *ifname;
225
226 if (argc < 2) {
227 usage(argv[0]);
228 return EXIT_FAILURE;
229 }
230
231 ifname = argv[1];
232
233 if (strlen(ifname) > IFNAMSIZ) {
234 fprintf(stderr, "Interface name '%s' is invalid\n", ifname);
235 return EXIT_FAILURE;
236 }
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800237
238 /*our MAC address */
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800239 static unsigned char src_mac[6];
240 static unsigned char src_ip[4];
241 int ifindex;
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800242// int InARP_SERVER;
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800243
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800244 if (((fd = socket(AF_PACKET, SOCK_PACKET, htons(ETH_P_ARP)))) == -1) {
245// if (((fd = socket (AF_PACKET, SOCK_RAW, 0))) == -1) {
246 printf("socket: [%s]\n", strerror(errno));
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800247 exit(-1);
248 }
249 //local mac address
250 memset(&ifreq_buffer, 0x00, sizeof(ifreq_buffer));
Jeremy Kerr115522d2016-02-25 10:24:14 +0800251 strcpy(ifreq_buffer.ifr_name, ifname);
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800252 ret = ioctl(fd, SIOCGIFHWADDR, &ifreq_buffer);
253 if (ret == -1) {
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800254 printf("ioctl2: [%s]\n", strerror(errno));
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800255 close(fd);
256 exit(-1);
257 }
258 memcpy(src_mac, ifreq_buffer.ifr_hwaddr.sa_data, ETH_ALEN);
Jeremy Kerr115522d2016-02-25 10:24:14 +0800259 show_mac_addr(ifname, src_mac);
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800260 //interface index
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800261 memset(&ifreq_buffer, 0x00, sizeof(ifreq_buffer));
Jeremy Kerr115522d2016-02-25 10:24:14 +0800262 strcpy(ifreq_buffer.ifr_name, ifname);
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800263 ret = ioctl(fd, SIOCGIFINDEX, &ifreq_buffer);
264 if (ret == -1) {
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800265 printf("ioctl4: [%s]\n", strerror(errno));
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800266 close(fd);
267 exit(-1);
268 }
269 ifindex = ifreq_buffer.ifr_ifindex;
270
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800271 int length = 0; /*length of the received frame */
272 static struct ETH_ARP_PACKET *inarp_req = (struct ETH_ARP_PACKET *)buffer; /* single packets are usually not bigger than 8192 bytes */
273 static struct ETH_ARP_PACKET inarp_resp; /* single packets are usually not bigger than 8192 bytes */
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800274 //argv[2]: file name used for storing node ip list
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800275 // line format in file: <node_id> <mac_addr> <ip_addr>
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800276 //get based address via EMS
277 //set socket as async
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800278// fcntl(fd, F_SETFL,O_NONBLOCK|FASYNC);
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800279 //got based address
280 while (1) {
281 //get local ip address
282 memset(&ifreq_buffer, 0x00, sizeof(ifreq_buffer));
Jeremy Kerr115522d2016-02-25 10:24:14 +0800283 strcpy(ifreq_buffer.ifr_name, ifname);
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800284 ret = ioctl(fd, SIOCGIFADDR, &ifreq_buffer);
285 if (ret == -1) {
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800286// printf("ioctl3: [%s]\n", strerror(errno));
287 sleep(1);
288 continue;
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800289 }
290
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800291 if (AF_INET == ifreq_buffer.ifr_addr.sa_family) {
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800292 memcpy(src_ip, &ifreq_buffer.ifr_addr.sa_data[2], 4);
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800293// show_ip_addr("local", (unsigned char *)&ifreq_buffer.ifr_addr.sa_data[2]);
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800294 //show_ip_addr("local", src_ip);
295 } else {
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800296 printf("unknown address family [%d]!\n",
297 ifreq_buffer.ifr_addr.sa_family);
298 sleep(1);
299 continue;
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800300 }
301
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800302 memset((void *)&inarp_resp, 0, sizeof inarp_resp);
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800303 length = recvfrom(fd, buffer, ETH_ARP_FRAME_LEN, 0, NULL, NULL);
304 if (length == -1) {
305 sleep(1);
306 }
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800307// printf("length = %d\r\nfd = %d\r\n", length, fd);
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800308 if (0 == memcmp(src_mac, inarp_req->eh.h_dest, ETH_ALEN)) {
309 if (ntohs(inarp_req->arp.ar_op) == ARPOP_InREQUEST) { //get a inverse arp request
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800310// printf("[Rsp] InRequest\n");
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800311 //dump_data("got InARP request packet", buffer, length);
312 //send inarp response
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800313
314 printf
315 ("src mac =%02x:%02x:%02x:%02x:%02x:%02x\r\n",
316 inarp_req->arp_data.src_mac[0],
317 inarp_req->arp_data.src_mac[1],
318 inarp_req->arp_data.src_mac[2],
319 inarp_req->arp_data.src_mac[3],
320 inarp_req->arp_data.src_mac[4],
321 inarp_req->arp_data.src_mac[5]
322 );
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800323 printf("src ip =%d:%d:%d:%d\r\n",
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800324 inarp_req->arp_data.src_ip[0],
325 inarp_req->arp_data.src_ip[1],
326 inarp_req->arp_data.src_ip[2],
327 inarp_req->arp_data.src_ip[3]
328 );
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800329 int fd_1;
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800330 if (((fd_1 =
331 socket(AF_PACKET, SOCK_RAW, 0))) == -1) {
332 printf("socket: [%s]\n",
333 strerror(errno));
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800334 exit(-1);
335 }
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800336 send_result =
337 send_arp_packet(fd_1, ifindex, &inarp_resp,
338 ARPOP_InREPLY,
339 inarp_req->arp_data.
340 dest_mac, src_ip,
341 inarp_req->arp_data.src_mac,
342 inarp_req->arp_data.src_ip);
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800343 close(fd_1);
344 if (send_result == -1) {
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800345 printf("[Rsp] sendto: [%s]\n",
346 strerror(errno));
347 sleep(1);
348 continue;
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800349 }
350 }
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800351// } else if (ntohs(inarp_req->arp.ar_op) == ARPOP_InREPLY) { //get a InARP Response
352// int node_id;
353// printf("[Rsp] InReply\n");
354// node_id = get_node_id_by_mac_address(inarp_req->arp_data.src_mac);
355// if (node_id == -1) {
356// //invalid node
357// printf("%02x:%02x:%02x:%02x:%02x:%02x does not belong to this rack.",
358// inarp_req->arp_data.src_mac[0],
359// inarp_req->arp_data.src_mac[1],
360// inarp_req->arp_data.src_mac[2],
361// inarp_req->arp_data.src_mac[3],
362// inarp_req->arp_data.src_mac[4],
363// inarp_req->arp_data.src_mac[5]
364// );
365// } else {
366 //valid node id
367// node[node_id].update_time.tv_sec = current_time.tv_sec;
368 //update or remain node's ip
369// if ((0 != memcmp(node[node_id].dest_ip, inarp_req->arp_data.src_ip, 4))) {
370 //ip address is changed.
371// static char ipv4_addr[16];
372// printf("[Rsp] update node[%d] ip @ %u\n", node_id+1, (unsigned)current_time.tv_sec);
373// show_mac_addr("[Rsp] ", inarp_req->arp_data.src_mac);
374// show_ip_addr("[Rsp] ", inarp_req->arp_data.src_ip);
375// memcpy(node[node_id].dest_ip, inarp_req->arp_data.src_ip, 4);
376// sprintf(ipv4_addr, "%d.%d.%d.%d",
377// inarp_req->arp_data.src_ip[0],
378// inarp_req->arp_data.src_ip[1],
379// inarp_req->arp_data.src_ip[2],
380// inarp_req->arp_data.src_ip[3]);
381// printf("[Rsp] update node[%d] ip @ %u\n", node_id+1, (unsigned)current_time.tv_sec);
382// }
383 memset(buffer, 0, sizeof(buffer));
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800384 }
385 }
386 close(fd);
387 return 0;
388}