xref: /mOS-networking-stack/core/src/arp.c (revision 8a941c7e)
176404edcSAsim Jamshed #include <stdint.h>
276404edcSAsim Jamshed #include <string.h>
376404edcSAsim Jamshed #include <sys/types.h>
476404edcSAsim Jamshed 
576404edcSAsim Jamshed #include "mtcp.h"
676404edcSAsim Jamshed #include "arp.h"
776404edcSAsim Jamshed #include "eth_out.h"
876404edcSAsim Jamshed #include "debug.h"
976404edcSAsim Jamshed #include "config.h"
1076404edcSAsim Jamshed 
1176404edcSAsim Jamshed #define ARP_PAD_LEN 			18
1276404edcSAsim Jamshed #define ARP_HEAD_LEN 			8
1376404edcSAsim Jamshed #define TS_GEQ(a, b)			((int32_t)((a)-(b)) >= 0)
1476404edcSAsim Jamshed #define SEC_TO_TS(a)		       	(a * 1000)
1576404edcSAsim Jamshed 
1676404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
1776404edcSAsim Jamshed enum arp_hrd_format
1876404edcSAsim Jamshed {
1976404edcSAsim Jamshed 	arp_hrd_ethernet = 1
2076404edcSAsim Jamshed };
2176404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
2276404edcSAsim Jamshed enum arp_opcode
2376404edcSAsim Jamshed {
2476404edcSAsim Jamshed 	arp_op_request = 1,
2576404edcSAsim Jamshed 	arp_op_reply = 2,
2676404edcSAsim Jamshed };
2776404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
2876404edcSAsim Jamshed struct arphdr
2976404edcSAsim Jamshed {
3076404edcSAsim Jamshed 	uint16_t ar_hrd;			/* hardware address format */
3176404edcSAsim Jamshed 	uint16_t ar_pro;			/* protocol address format */
3276404edcSAsim Jamshed 	uint8_t ar_hln;				/* hardware address length */
3376404edcSAsim Jamshed 	uint8_t ar_pln;				/* protocol address length */
3476404edcSAsim Jamshed 	uint16_t ar_op;				/* arp opcode */
3576404edcSAsim Jamshed 
3676404edcSAsim Jamshed 	uint8_t ar_sha[ETH_ALEN];	/* sender hardware address */
3776404edcSAsim Jamshed 	uint32_t ar_sip;			/* sender ip address */
3876404edcSAsim Jamshed 	uint8_t ar_tha[ETH_ALEN];	/* targe hardware address */
3976404edcSAsim Jamshed 	uint32_t ar_tip;			/* target ip address */
4076404edcSAsim Jamshed 
4176404edcSAsim Jamshed 	uint8_t pad[ARP_PAD_LEN];
4276404edcSAsim Jamshed } __attribute__ ((packed));
4376404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
4476404edcSAsim Jamshed struct arp_queue_entry
4576404edcSAsim Jamshed {
4676404edcSAsim Jamshed 	uint32_t ip;
4776404edcSAsim Jamshed 	int nif_out;
4876404edcSAsim Jamshed 	uint32_t ts_out;
4976404edcSAsim Jamshed 
5076404edcSAsim Jamshed 	TAILQ_ENTRY(arp_queue_entry) arp_link;
5176404edcSAsim Jamshed };
5276404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
5376404edcSAsim Jamshed struct arp_manager
5476404edcSAsim Jamshed {
5576404edcSAsim Jamshed 	TAILQ_HEAD (, arp_queue_entry) list;
5676404edcSAsim Jamshed 	pthread_mutex_t lock;
5776404edcSAsim Jamshed };
5876404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
5976404edcSAsim Jamshed struct arp_manager g_arpm;
6076404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
6176404edcSAsim Jamshed void
6276404edcSAsim Jamshed DumpARPPacket(struct arphdr *arph);
6376404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
6476404edcSAsim Jamshed int
InitARPTable()6576404edcSAsim Jamshed InitARPTable()
6676404edcSAsim Jamshed {
6776404edcSAsim Jamshed 	TAILQ_INIT(&g_arpm.list);
6876404edcSAsim Jamshed 	pthread_mutex_init(&g_arpm.lock, NULL);
6976404edcSAsim Jamshed 
7076404edcSAsim Jamshed 	return 0;
7176404edcSAsim Jamshed }
7276404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
7376404edcSAsim Jamshed unsigned char *
GetHWaddr(uint32_t ip)7476404edcSAsim Jamshed GetHWaddr(uint32_t ip)
7576404edcSAsim Jamshed {
7676404edcSAsim Jamshed 	int i;
7776404edcSAsim Jamshed 	unsigned char *haddr = NULL;
7876404edcSAsim Jamshed 	for (i = 0; i < g_config.mos->netdev_table->num; i++) {
7976404edcSAsim Jamshed 		if (ip == g_config.mos->netdev_table->ent[i]->ip_addr) {
8076404edcSAsim Jamshed 			haddr = g_config.mos->netdev_table->ent[i]->haddr;
8176404edcSAsim Jamshed 			break;
8276404edcSAsim Jamshed 		}
8376404edcSAsim Jamshed 	}
8476404edcSAsim Jamshed 
8576404edcSAsim Jamshed 	return haddr;
8676404edcSAsim Jamshed }
8776404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
8876404edcSAsim Jamshed unsigned char *
GetDestinationHWaddr(uint32_t dip)8976404edcSAsim Jamshed GetDestinationHWaddr(uint32_t dip)
9076404edcSAsim Jamshed {
9176404edcSAsim Jamshed 	unsigned char *d_haddr = NULL;
9276404edcSAsim Jamshed 	int prefix = 0;
9376404edcSAsim Jamshed 	int i;
9476404edcSAsim Jamshed 
9576404edcSAsim Jamshed #ifdef L3_TRANSPARENT
9676404edcSAsim Jamshed 	static unsigned char none_haddr[ETH_ALEN] = {0,};
9776404edcSAsim Jamshed 	return none_haddr;
9876404edcSAsim Jamshed #endif
9976404edcSAsim Jamshed 
10076404edcSAsim Jamshed 	/* Longest prefix matching */
10176404edcSAsim Jamshed 	for (i = 0; i < g_config.mos->arp_table->num; i++) {
10276404edcSAsim Jamshed 		if (g_config.mos->arp_table->ent[i]->prefix == 1) {
10376404edcSAsim Jamshed 			if (g_config.mos->arp_table->ent[i]->ip == dip) {
10476404edcSAsim Jamshed 				d_haddr = g_config.mos->arp_table->ent[i]->haddr;
10576404edcSAsim Jamshed 				break;
10676404edcSAsim Jamshed 			}
10776404edcSAsim Jamshed 		} else {
10876404edcSAsim Jamshed 			if ((dip & g_config.mos->arp_table->ent[i]->mask) ==
10976404edcSAsim Jamshed 					g_config.mos->arp_table->ent[i]->masked_ip) {
11076404edcSAsim Jamshed 
11176404edcSAsim Jamshed 				if (g_config.mos->arp_table->ent[i]->prefix > prefix) {
11276404edcSAsim Jamshed 					d_haddr = g_config.mos->arp_table->ent[i]->haddr;
11376404edcSAsim Jamshed 					prefix = g_config.mos->arp_table->ent[i]->prefix;
11476404edcSAsim Jamshed 				}
11576404edcSAsim Jamshed 			}
11676404edcSAsim Jamshed 		}
11776404edcSAsim Jamshed 	}
11876404edcSAsim Jamshed 
11976404edcSAsim Jamshed 	return d_haddr;
12076404edcSAsim Jamshed }
12176404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
12276404edcSAsim Jamshed static int
ARPOutput(struct mtcp_manager * mtcp,int nif,int opcode,uint32_t dst_ip,unsigned char * dst_haddr,unsigned char * target_haddr)12376404edcSAsim Jamshed ARPOutput(struct mtcp_manager *mtcp, int nif, int opcode,
12476404edcSAsim Jamshed 	  uint32_t dst_ip, unsigned char *dst_haddr,
12576404edcSAsim Jamshed 	  unsigned char *target_haddr)
12676404edcSAsim Jamshed {
12776404edcSAsim Jamshed 	if (!dst_haddr)
12876404edcSAsim Jamshed 		return -1;
12976404edcSAsim Jamshed 
13076404edcSAsim Jamshed 	/* Allocate a buffer */
13176404edcSAsim Jamshed 	struct arphdr *arph = (struct arphdr *)EthernetOutput(mtcp, NULL,
13276404edcSAsim Jamshed 			ETH_P_ARP, nif, dst_haddr, sizeof(struct arphdr), 0);
13376404edcSAsim Jamshed 	if (!arph) {
13476404edcSAsim Jamshed 		return -1;
13576404edcSAsim Jamshed 	}
13676404edcSAsim Jamshed 
13776404edcSAsim Jamshed 	/* Fill arp header */
13876404edcSAsim Jamshed 	arph->ar_hrd = htons(arp_hrd_ethernet);
13976404edcSAsim Jamshed 	arph->ar_pro = htons(ETH_P_IP);
14076404edcSAsim Jamshed 	arph->ar_hln = ETH_ALEN;
14176404edcSAsim Jamshed 	arph->ar_pln = 4;
14276404edcSAsim Jamshed 	arph->ar_op = htons(opcode);
14376404edcSAsim Jamshed 
14476404edcSAsim Jamshed 	/* Fill arp body */
14576404edcSAsim Jamshed 	arph->ar_sip = g_config.mos->netdev_table->ent[nif]->ip_addr;
14676404edcSAsim Jamshed 	arph->ar_tip = dst_ip;
14776404edcSAsim Jamshed 
14876404edcSAsim Jamshed 	memcpy(arph->ar_sha, g_config.mos->netdev_table->ent[nif]->haddr, arph->ar_hln);
14976404edcSAsim Jamshed 	if (target_haddr) {
15076404edcSAsim Jamshed 		memcpy(arph->ar_tha, target_haddr, arph->ar_hln);
15176404edcSAsim Jamshed 	} else {
15276404edcSAsim Jamshed 		memcpy(arph->ar_tha, dst_haddr, arph->ar_hln);
15376404edcSAsim Jamshed 	}
15476404edcSAsim Jamshed 	memset(arph->pad, 0, ARP_PAD_LEN);
15576404edcSAsim Jamshed 
15676404edcSAsim Jamshed #if DBGMSG
15776404edcSAsim Jamshed 	DumpARPPacket(arph);
15876404edcSAsim Jamshed #endif
15976404edcSAsim Jamshed 
16076404edcSAsim Jamshed 	return 0;
16176404edcSAsim Jamshed }
16276404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
16376404edcSAsim Jamshed int
RegisterARPEntry(uint32_t ip,const unsigned char * haddr)16476404edcSAsim Jamshed RegisterARPEntry(uint32_t ip, const unsigned char *haddr)
16576404edcSAsim Jamshed {
16676404edcSAsim Jamshed 	int idx = g_config.mos->arp_table->num;
16776404edcSAsim Jamshed 	g_config.mos->arp_table->ent[idx] = calloc(1, sizeof(struct _arp_entry));
16876404edcSAsim Jamshed 	if (!g_config.mos->arp_table->ent[idx])
16976404edcSAsim Jamshed 		exit(0);
17076404edcSAsim Jamshed 	g_config.mos->arp_table->ent[idx]->prefix = 32;
17176404edcSAsim Jamshed 	g_config.mos->arp_table->ent[idx]->ip = ip;
17276404edcSAsim Jamshed 	memcpy(g_config.mos->arp_table->ent[idx]->haddr, haddr, ETH_ALEN);
17376404edcSAsim Jamshed 	g_config.mos->arp_table->ent[idx]->mask = -1;
17476404edcSAsim Jamshed 	g_config.mos->arp_table->ent[idx]->masked_ip = ip;
17576404edcSAsim Jamshed 
17676404edcSAsim Jamshed 	g_config.mos->arp_table->num = idx + 1;
17776404edcSAsim Jamshed 
17876404edcSAsim Jamshed 	TRACE_CONFIG("Learned new arp entry.\n");
17976404edcSAsim Jamshed 	PrintARPTable();
18076404edcSAsim Jamshed 
18176404edcSAsim Jamshed 	return 0;
18276404edcSAsim Jamshed }
18376404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
18476404edcSAsim Jamshed void
RequestARP(mtcp_manager_t mtcp,uint32_t ip,int nif,uint32_t cur_ts)18576404edcSAsim Jamshed RequestARP(mtcp_manager_t mtcp, uint32_t ip, int nif, uint32_t cur_ts)
18676404edcSAsim Jamshed {
18776404edcSAsim Jamshed 	struct arp_queue_entry *ent;
18876404edcSAsim Jamshed 	unsigned char haddr[ETH_ALEN];
18976404edcSAsim Jamshed 	unsigned char taddr[ETH_ALEN];
19076404edcSAsim Jamshed 
19176404edcSAsim Jamshed 	pthread_mutex_lock(&g_arpm.lock);
19276404edcSAsim Jamshed 	/* if the arp request is in progress, return */
19376404edcSAsim Jamshed 	TAILQ_FOREACH(ent, &g_arpm.list, arp_link) {
19476404edcSAsim Jamshed 		if (ent->ip == ip) {
19576404edcSAsim Jamshed 			pthread_mutex_unlock(&g_arpm.lock);
19676404edcSAsim Jamshed 			return;
19776404edcSAsim Jamshed 		}
19876404edcSAsim Jamshed 	}
19976404edcSAsim Jamshed 
20076404edcSAsim Jamshed 	ent = (struct arp_queue_entry *)calloc(1, sizeof(struct arp_queue_entry));
20176404edcSAsim Jamshed 	if (ent == NULL) {
20276404edcSAsim Jamshed 		TRACE_ERROR("Unable to allocate memory for ARP entry!\n");
20376404edcSAsim Jamshed 		exit(EXIT_FAILURE);
20476404edcSAsim Jamshed 	}
20576404edcSAsim Jamshed 	ent->ip = ip;
20676404edcSAsim Jamshed 	ent->nif_out = nif;
20776404edcSAsim Jamshed 	ent->ts_out = cur_ts;
20876404edcSAsim Jamshed 	TAILQ_INSERT_TAIL(&g_arpm.list, ent, arp_link);
20976404edcSAsim Jamshed 	pthread_mutex_unlock(&g_arpm.lock);
21076404edcSAsim Jamshed 
21176404edcSAsim Jamshed 	/* else, broadcast arp request */
21276404edcSAsim Jamshed 	memset(haddr, 0xFF, ETH_ALEN);
21376404edcSAsim Jamshed 	memset(taddr, 0x00, ETH_ALEN);
21476404edcSAsim Jamshed 	ARPOutput(mtcp, nif, arp_op_request, ip, haddr, taddr);
21576404edcSAsim Jamshed }
21676404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
21776404edcSAsim Jamshed static int
ProcessARPRequest(mtcp_manager_t mtcp,struct arphdr * arph,int nif,uint32_t cur_ts)21876404edcSAsim Jamshed ProcessARPRequest(mtcp_manager_t mtcp,
21976404edcSAsim Jamshed 		struct arphdr *arph, int nif, uint32_t cur_ts)
22076404edcSAsim Jamshed {
22176404edcSAsim Jamshed 	unsigned char *temp;
22276404edcSAsim Jamshed 
22376404edcSAsim Jamshed 	/* register the arp entry if not exist */
22476404edcSAsim Jamshed 	temp = GetDestinationHWaddr(arph->ar_sip);
22576404edcSAsim Jamshed 	if (!temp) {
22676404edcSAsim Jamshed 		RegisterARPEntry(arph->ar_sip, arph->ar_sha);
22776404edcSAsim Jamshed 	}
22876404edcSAsim Jamshed 
22976404edcSAsim Jamshed 	/* send arp reply */
23076404edcSAsim Jamshed 	ARPOutput(mtcp, nif, arp_op_reply, arph->ar_sip, arph->ar_sha, NULL);
23176404edcSAsim Jamshed 
23276404edcSAsim Jamshed 	return 0;
23376404edcSAsim Jamshed }
23476404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
23576404edcSAsim Jamshed static int
ProcessARPReply(mtcp_manager_t mtcp,struct arphdr * arph,uint32_t cur_ts)23676404edcSAsim Jamshed ProcessARPReply(mtcp_manager_t mtcp, struct arphdr *arph, uint32_t cur_ts)
23776404edcSAsim Jamshed {
23876404edcSAsim Jamshed 	unsigned char *temp;
23976404edcSAsim Jamshed 	struct arp_queue_entry *ent;
24076404edcSAsim Jamshed 
24176404edcSAsim Jamshed 	/* register the arp entry if not exist */
24276404edcSAsim Jamshed 	temp = GetDestinationHWaddr(arph->ar_sip);
24376404edcSAsim Jamshed 	if (!temp) {
24476404edcSAsim Jamshed 		RegisterARPEntry(arph->ar_sip, arph->ar_sha);
24576404edcSAsim Jamshed 	}
24676404edcSAsim Jamshed 
24776404edcSAsim Jamshed 	/* remove from the arp request queue */
24876404edcSAsim Jamshed 	pthread_mutex_lock(&g_arpm.lock);
24976404edcSAsim Jamshed 	TAILQ_FOREACH(ent, &g_arpm.list, arp_link) {
25076404edcSAsim Jamshed 		if (ent->ip == arph->ar_sip) {
25176404edcSAsim Jamshed 			TAILQ_REMOVE(&g_arpm.list, ent, arp_link);
25276404edcSAsim Jamshed 			free(ent);
25376404edcSAsim Jamshed 			break;
25476404edcSAsim Jamshed 		}
25576404edcSAsim Jamshed 	}
25676404edcSAsim Jamshed 	pthread_mutex_unlock(&g_arpm.lock);
25776404edcSAsim Jamshed 
25876404edcSAsim Jamshed 	return 0;
25976404edcSAsim Jamshed }
26076404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
26176404edcSAsim Jamshed int
ProcessARPPacket(mtcp_manager_t mtcp,uint32_t cur_ts,const int ifidx,unsigned char * pkt_data,int len)26276404edcSAsim Jamshed ProcessARPPacket(mtcp_manager_t mtcp, uint32_t cur_ts,
26376404edcSAsim Jamshed 		                  const int ifidx, unsigned char *pkt_data, int len)
26476404edcSAsim Jamshed {
26576404edcSAsim Jamshed 	struct arphdr *arph = (struct arphdr *)(pkt_data + sizeof(struct ethhdr));
26676404edcSAsim Jamshed 	int i;
26776404edcSAsim Jamshed 	int to_me = FALSE;
26876404edcSAsim Jamshed 
26976404edcSAsim Jamshed 	/* process the arp messages destined to me */
27076404edcSAsim Jamshed 	for (i = 0; i < g_config.mos->netdev_table->num; i++) {
27176404edcSAsim Jamshed 		if (arph->ar_tip == g_config.mos->netdev_table->ent[i]->ip_addr) {
27276404edcSAsim Jamshed 			to_me = TRUE;
27376404edcSAsim Jamshed 		}
27476404edcSAsim Jamshed 	}
27576404edcSAsim Jamshed 
27676404edcSAsim Jamshed 	if (!to_me)
27776404edcSAsim Jamshed 		return TRUE;
27876404edcSAsim Jamshed 
27976404edcSAsim Jamshed #if DBGMSG
28076404edcSAsim Jamshed 	DumpARPPacket(arph);
28176404edcSAsim Jamshed #endif
28276404edcSAsim Jamshed 
28376404edcSAsim Jamshed 	switch (ntohs(arph->ar_op)) {
28476404edcSAsim Jamshed 		case arp_op_request:
28576404edcSAsim Jamshed 			ProcessARPRequest(mtcp, arph, ifidx, cur_ts);
28676404edcSAsim Jamshed 			break;
28776404edcSAsim Jamshed 
28876404edcSAsim Jamshed 		case arp_op_reply:
28976404edcSAsim Jamshed 			ProcessARPReply(mtcp, arph, cur_ts);
29076404edcSAsim Jamshed 			break;
29176404edcSAsim Jamshed 
29276404edcSAsim Jamshed 		default:
29376404edcSAsim Jamshed 			break;
29476404edcSAsim Jamshed 	}
29576404edcSAsim Jamshed 
29676404edcSAsim Jamshed 	return TRUE;
29776404edcSAsim Jamshed }
29876404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
29976404edcSAsim Jamshed // Publish my address
30076404edcSAsim Jamshed void
PublishARP(mtcp_manager_t mtcp)30176404edcSAsim Jamshed PublishARP(mtcp_manager_t mtcp)
30276404edcSAsim Jamshed {
30376404edcSAsim Jamshed 	int i;
30476404edcSAsim Jamshed 	for (i = 0; i < g_config.mos->netdev_table->num; i++) {
30576404edcSAsim Jamshed 		ARPOutput(mtcp, g_config.mos->netdev_table->ent[i]->ifindex, arp_op_request, 0, NULL, NULL);
30676404edcSAsim Jamshed 	}
30776404edcSAsim Jamshed }
30876404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
30976404edcSAsim Jamshed /* ARPTimer: wakes up every milisecond and check the ARP timeout              */
31076404edcSAsim Jamshed /*           timeout is set to 1 second                                       */
31176404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
31276404edcSAsim Jamshed void
ARPTimer(mtcp_manager_t mtcp,uint32_t cur_ts)31376404edcSAsim Jamshed ARPTimer(mtcp_manager_t mtcp, uint32_t cur_ts)
31476404edcSAsim Jamshed {
315*8a941c7eSAsim Jamshed         struct arp_queue_entry *ent, *ent_tmp;
31676404edcSAsim Jamshed 
31776404edcSAsim Jamshed         /* if the arp requet is timed out, retransmit */
31876404edcSAsim Jamshed         pthread_mutex_lock(&g_arpm.lock);
319*8a941c7eSAsim Jamshed         TAILQ_FOREACH_SAFE(ent, &g_arpm.list, arp_link, ent_tmp) {
32076404edcSAsim Jamshed                 if (TS_GEQ(cur_ts, ent->ts_out + SEC_TO_TS(ARP_TIMEOUT_SEC))) {
32176404edcSAsim Jamshed                         TRACE_INFO("[CPU%2d] ARP request timed out.\n",
32276404edcSAsim Jamshed 				   mtcp->ctx->cpu);
32376404edcSAsim Jamshed                         TAILQ_REMOVE(&g_arpm.list, ent, arp_link);
32476404edcSAsim Jamshed                         free(ent);
32576404edcSAsim Jamshed                 }
32676404edcSAsim Jamshed         }
32776404edcSAsim Jamshed         pthread_mutex_unlock(&g_arpm.lock);
32876404edcSAsim Jamshed }
32976404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
33076404edcSAsim Jamshed void
PrintARPTable()33176404edcSAsim Jamshed PrintARPTable()
33276404edcSAsim Jamshed {
33376404edcSAsim Jamshed 	int i;
33476404edcSAsim Jamshed 
33576404edcSAsim Jamshed 	/* print out process start information */
33676404edcSAsim Jamshed 	TRACE_CONFIG("ARP Table:\n");
33776404edcSAsim Jamshed 	for (i = 0; i < g_config.mos->arp_table->num; i++) {
33876404edcSAsim Jamshed 
33976404edcSAsim Jamshed 		uint8_t *da = (uint8_t *)&g_config.mos->arp_table->ent[i]->ip;
34076404edcSAsim Jamshed 
34176404edcSAsim Jamshed 		TRACE_CONFIG("IP addr: %u.%u.%u.%u, "
34276404edcSAsim Jamshed 				"dst_hwaddr: %02X:%02X:%02X:%02X:%02X:%02X\n",
34376404edcSAsim Jamshed 				da[0], da[1], da[2], da[3],
34476404edcSAsim Jamshed 				g_config.mos->arp_table->ent[i]->haddr[0],
34576404edcSAsim Jamshed 				g_config.mos->arp_table->ent[i]->haddr[1],
34676404edcSAsim Jamshed 				g_config.mos->arp_table->ent[i]->haddr[2],
34776404edcSAsim Jamshed 				g_config.mos->arp_table->ent[i]->haddr[3],
34876404edcSAsim Jamshed 				g_config.mos->arp_table->ent[i]->haddr[4],
34976404edcSAsim Jamshed 				g_config.mos->arp_table->ent[i]->haddr[5]);
35076404edcSAsim Jamshed 	}
35176404edcSAsim Jamshed 	if (g_config.mos->arp_table->num == 0)
35276404edcSAsim Jamshed 		TRACE_CONFIG("(blank)\n");
35376404edcSAsim Jamshed 
35476404edcSAsim Jamshed 	TRACE_CONFIG("----------------------------------------------------------"
35576404edcSAsim Jamshed 			"-----------------------\n");
35676404edcSAsim Jamshed }
35776404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
35876404edcSAsim Jamshed void
DumpARPPacket(struct arphdr * arph)35976404edcSAsim Jamshed DumpARPPacket(struct arphdr *arph)
36076404edcSAsim Jamshed {
36176404edcSAsim Jamshed 	uint8_t *t;
36276404edcSAsim Jamshed 
36376404edcSAsim Jamshed 	fprintf(stderr, "ARP header: \n");
36476404edcSAsim Jamshed 	fprintf(stderr, "Hareware type: %d (len: %d), "
36576404edcSAsim Jamshed 			"protocol type: %d (len: %d), opcode: %d\n",
36676404edcSAsim Jamshed 			ntohs(arph->ar_hrd), arph->ar_hln,
36776404edcSAsim Jamshed 			ntohs(arph->ar_pro), arph->ar_pln, ntohs(arph->ar_op));
36876404edcSAsim Jamshed 	t = (uint8_t *)&arph->ar_sip;
36976404edcSAsim Jamshed 	fprintf(stderr, "Sender IP: %u.%u.%u.%u, "
37076404edcSAsim Jamshed 			"haddr: %02X:%02X:%02X:%02X:%02X:%02X\n",
37176404edcSAsim Jamshed 			t[0], t[1], t[2], t[3],
37276404edcSAsim Jamshed 			arph->ar_sha[0], arph->ar_sha[1], arph->ar_sha[2],
37376404edcSAsim Jamshed 			arph->ar_sha[3], arph->ar_sha[4], arph->ar_sha[5]);
37476404edcSAsim Jamshed 	t = (uint8_t *)&arph->ar_tip;
37576404edcSAsim Jamshed 	fprintf(stderr, "Target IP: %u.%u.%u.%u, "
37676404edcSAsim Jamshed 			"haddr: %02X:%02X:%02X:%02X:%02X:%02X\n",
37776404edcSAsim Jamshed 			t[0], t[1], t[2], t[3],
37876404edcSAsim Jamshed 			arph->ar_tha[0], arph->ar_tha[1], arph->ar_tha[2],
37976404edcSAsim Jamshed 			arph->ar_tha[3], arph->ar_tha[4], arph->ar_tha[5]);
38076404edcSAsim Jamshed }
38176404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
38276404edcSAsim Jamshed void
ForwardARPPacket(struct mtcp_manager * mtcp,struct pkt_ctx * pctx)38376404edcSAsim Jamshed ForwardARPPacket(struct mtcp_manager *mtcp, struct pkt_ctx *pctx)
38476404edcSAsim Jamshed {
38576404edcSAsim Jamshed 	unsigned char *haddr;
38676404edcSAsim Jamshed 
38776404edcSAsim Jamshed 	if (g_config.mos->nic_forward_table != NULL) {
38876404edcSAsim Jamshed 		pctx->out_ifidx =
389a834ea89SAsim Jamshed 			g_config.mos->nic_forward_table->nic_fwd_table[pctx->p.in_ifidx];
39076404edcSAsim Jamshed 		if (pctx->out_ifidx != -1) {
39176404edcSAsim Jamshed 			haddr = pctx->p.ethh->h_dest;
39276404edcSAsim Jamshed 			struct arphdr *arph = (struct arphdr *)
39376404edcSAsim Jamshed 				EthernetOutput(mtcp, NULL, ETH_P_ARP,
39476404edcSAsim Jamshed 					       pctx->out_ifidx, haddr,
39576404edcSAsim Jamshed 					       sizeof(struct arphdr), 0);
39676404edcSAsim Jamshed 			if (!arph)
39776404edcSAsim Jamshed 				return;
39876404edcSAsim Jamshed 			memcpy(arph, (pctx->p.ethh + 1), sizeof(struct arphdr));
39976404edcSAsim Jamshed 		}
40076404edcSAsim Jamshed 	}
40176404edcSAsim Jamshed }
40276404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
403