📄 m_arp.c
字号:
{
dtrap("m_arp 0\n");
return;
}
outpkt->net = pkt->net; /* send back out the iface it came from */
in = (struct arp_hdr *)(pkt->nb_buff + ETHHDR_SIZE);
out = (struct arp_hdr *)(outpkt->nb_buff + ETHHDR_SIZE);
/* prepare outgoing arp packet */
out->ar_hd = ARPHW;
out->ar_pro = ARPIP;
out->ar_hln = 6;
out->ar_pln = 4;
out->ar_op = ARREP;
out->ar_tpa = in->ar_spa; /* swap IP addresses */
out->ar_spa = in->ar_tpa;
MEMCPY(out->ar_tha, in->ar_sha, 6); /* move his MAC address */
MEMCPY(out->ar_sha, outpkt->net->n_mib->ifPhysAddress, 6); /* fill in our mac address */
/* prepend ethernet unicast header to arp reply */
ethin = (struct ethhdr *)(pkt->nb_buff + ETHHDR_BIAS);
ethout = (struct ethhdr *)(outpkt->nb_buff + ETHHDR_BIAS);
MEMCPY(ethout->e_dst, ethin->e_src, 6);
MEMCPY(ethout->e_src, outpkt->net->n_mib->ifPhysAddress, 6);
ethout->e_type = ET_ARP; /* 0x0806 - ARP type on ethernet */
#ifdef NO_CC_PACKING /* move ARP fields to proper network boundaries */
{
struct arp_wire * arwp = (struct arp_wire *)out;
MEMMOVE(&arwp->data[AR_SHA], out->ar_sha, 6);
MEMMOVE(&arwp->data[AR_SPA], &out->ar_spa, 4);
MEMMOVE(&arwp->data[AR_THA], out->ar_tha, 6);
MEMMOVE(&arwp->data[AR_TPA], &out->ar_tpa, 4);
}
#endif /* NO_CC_PACKING */
outpkt->nb_plen = ETHHDR_SIZE + sizeof(struct arp_hdr);
outpkt->nb_prot = outpkt->nb_buff;
outpkt->net->pkt_send(outpkt);
/* input 'pkt' will be freed by caller */
arpRepsOut++;
}
/* FUNCTION: arprcv()
*
* arprcv(PACKET) - process an incoming arp packet.
*
*
* PARAM1: PACKET pkt
*
* RETURNS: Returns 0 if it was for us,
* ENP_NOT_MINE (1) if the arp packet is not for my IP
* address, else a negative error code.
*/
int
arprcv(PACKET pkt)
{
struct arp_hdr * arphdr;
struct arptabent * tp;
arphdr = (struct arp_hdr *)(pkt->nb_buff + ETHHDR_SIZE);
#ifdef NO_CC_PACKING /* force ARP fields to local CPU valid boundaries */
{
struct arp_wire * arwp = (struct arp_wire *)arphdr;
MEMMOVE(&arphdr->ar_tpa, &arwp->data[AR_TPA], 4);
MEMMOVE(arphdr->ar_tha, &arwp->data[AR_THA], 6);
MEMMOVE(&arphdr->ar_spa, &arwp->data[AR_SPA], 4);
MEMMOVE(arphdr->ar_sha, &arwp->data[AR_SHA], 6);
}
#endif /* NO_CC_PACKING */
/* check ARP's target IP against our net's: */
if(arphdr->ar_tpa != pkt->net->n_ipaddr)
{
LOCK_NET_RESOURCE(FREEQ_RESID);
pk_free(pkt); /* not for us, dump & ret (proxy here later?) */
UNLOCK_NET_RESOURCE(FREEQ_RESID);
return(ENP_NOT_MINE);
}
if (arphdr->ar_op == ARREQ) /* is it an arp request? */
{
arpReqsIn++; /* count these */
arpReply(pkt); /* send arp reply */
/* make partial ARP table entry */
make_arp_entry(arphdr->ar_spa, pkt->net);
/* fall thru to arp reply logic to finish our table entry */
}
else /* ARP reply, count and fall thru to logic to update table */
{
arpRepsIn++;
}
/* scan table for matching entry */
/* check this for default gateway situations later, JB */
for (tp = arp_table; tp <= &arp_table[MAXARPS-1]; tp++)
{
if (tp->t_pro_addr == arphdr->ar_spa) /* we found IP address, update entry */
{
MEMCPY(tp->t_phy_addr, arphdr->ar_sha, 6); /* update MAC adddress */
tp->lasttime = cticks;
if (tp->pending) /* packet waiting for this IP entry? */
{
PACKET outpkt = tp->pending;
tp->pending = NULL;
et_send(outpkt, tp); /* try send again */
}
LOCK_NET_RESOURCE(FREEQ_RESID);
pk_free(pkt);
UNLOCK_NET_RESOURCE(FREEQ_RESID);
return(0);
}
}
/* fall to here if packet is not in table */
LOCK_NET_RESOURCE(FREEQ_RESID);
pk_free(pkt);
UNLOCK_NET_RESOURCE(FREEQ_RESID);
return ENP_NOT_MINE;
}
/* FUNCTION: send_via_arp()
*
* send_via_arp() - Called when we want to send an IP packet on a
* media (i.e. ethernet) which supports ARP. packet is passed, along
* with target IP address, which may be the packet's dest_ip or a
* gateway/router. We check the ARP cache (and scan arp table if
* required) for MAC address matching the passed dest_ip address. If
* the MAC address is not already known, we broadcast an arp request
* for the missing IP address and attach the packet to the "pending"
* pointer. The packet will be sent when the ARP reply comes in, or
* freed if we time out. We flush the cache every second to force the
* regular freeing of any "pending" packets. We flush every entry on
* the ageout interval so bogus ARP addresses won't get permanently
* wedged in the table. This happens when someone replaces a PC's MAC
* adapter but does not change the PC's IP address.
*
* PARAM1: PACKET pkt
* PARAM2: ip_addr dest_ip
*
* RETURNS: Returns 0 if packet went to mac sender; ENP_SEND_PENDING
* if awaiting arp reply, or SEND_FAILED if error
*/
int
send_via_arp(PACKET pkt, ip_addr dest_ip)
{
struct arptabent * tp;
/* Force refresh of cache once a second */
if ((cachetime + TPS) < cticks)
arpcache = NULL;
/* look at the last ARP entry used. Good chance it's ours: */
if (arpcache && arpcache->t_pro_addr == dest_ip)
return(et_send(pkt, arpcache));
/* scan arp table for an existing entry */
for (tp = arp_table; tp <= &arp_table[MAXARPS-1]; tp++)
{
/* age out pending entrys here: */
if (tp->pending)
{
/* if over a second old.. */
if (( cticks > TPS ) &&
(tp->createtime < (cticks - TPS)))
{
LOCK_NET_RESOURCE(FREEQ_RESID);
pk_free(tp->pending); /* free the blocked IP packet */
UNLOCK_NET_RESOURCE(FREEQ_RESID);
tp->pending = NULL; /* clear pointer */
tp->t_pro_addr = 0; /* marks entry as "unused" */
}
}
/* See if it's time to age out this entry anyway. We don't kill
* entries we've referenced in the last second for
*/
if (((tp->createtime + (TPS * (u_long)arp_ageout)) < cticks) &&
(tp->lasttime + TPS) < cticks)
{
tp->t_pro_addr = 0; /* marks entry as "unused" */
}
if (tp->t_pro_addr == dest_ip) /* we found our entry */
{
if (tp->pending) /* arp already pending for this IP? */
{
LOCK_NET_RESOURCE(FREEQ_RESID);
pk_free(pkt); /* sorry, we have to dump this one.. */
UNLOCK_NET_RESOURCE(FREEQ_RESID);
return SEND_DROPPED; /* packet already waiting for this IP entry */
}
else /* just send it */
{
arpcache = tp; /* cache this entry */
cachetime = cticks; /* mark time we cached */
return(et_send(pkt, tp));
}
}
}
return(send_arp(pkt, dest_ip));
}
#ifdef NET_STATS
/* FUNCTION: arp_stats()
*
* PARAM1: void * pio
*
* RETURNS:
*/
int
arp_stats(void * pio) /* passed output device */
{
struct arptabent * atp;
int i;
int arp_entrys = 0;
ns_printf(pio, "arp Requests In: %u, out: %u\n", arpReqsIn, arpReqsOut);
ns_printf(pio, "arp Replys In: %u, out: %u\n", arpRepsIn, arpRepsOut);
/* count number of arp entrys in use: */
for (i = 0; i < MAXARPS; i++)
{
if (arp_table[i].t_pro_addr)
arp_entrys++;
}
if (arp_entrys)
{
ns_printf(pio, "X) MAC Address iface pend IP ctime ltime\n");
for (i = 0; i < MAXARPS; i++)
{
atp = &arp_table[i];
if (atp->t_pro_addr)
{
ns_printf(pio, "%d) ", i);
ns_printf(pio, "%02x%02x%02x-%02x%02x%02x ",
atp->t_phy_addr[0],
atp->t_phy_addr[1],
atp->t_phy_addr[2],
atp->t_phy_addr[3],
atp->t_phy_addr[4],
atp->t_phy_addr[5]);
ns_printf(pio, " %d %s %u.%u.%u.%u %lu %lu\n",
if_netnumber(atp->net)+1,
atp->pending?"Y":"N",
PUSH_IPADDR(atp->t_pro_addr),
(long)atp->createtime,
(long)atp->lasttime);
}
}
}
else
{
ns_printf(pio, "Currently no arp table entrys.\n");
}
return 0;
}
#endif /* NET_STATS */
/* end of file et_arp.c */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -