/* * Convert an ARP request into a reply and send it. * Notes: Re-uses buffer. Pad to length = 46. */ void arp_reply(struct nbuf *nbuf) { struct ether_arp *arp = nbuf->nh.arph; struct nic *d = nbuf->nic; /* If we are not the target, ignore the request. */ if (bcmp(arp->arp_tpa, &d->ip_addr, sizeof(arp->arp_tpa))) { return; } arp->arp_op = htons(ARPOP_REPLY); /* source becomes target */ bcopy(arp->arp_sha, arp->arp_tha, sizeof(arp->arp_tha)); bcopy(arp->arp_spa, arp->arp_tpa, sizeof(arp->arp_tpa)); /* here becomes source */ bcopy(d->node_addr, arp->arp_sha, sizeof(arp->arp_sha)); bcopy(&d->ip_addr, arp->arp_spa, sizeof(arp->arp_spa)); /* * No need to get fancy here. If the send fails, the * requestor will just ask again. */ (void) arpsend(nbuf,arp->arp_tha, ETHERTYPE_ARP); }
/*------------------------------------------------------------------------ * arptimer - Iterate through ARP cache, aging (possibly removing) entries *------------------------------------------------------------------------ * gran - time since last iteration */ void arptimer(int gran) { struct arpentry *pae; STATWORD ps; int i; disable(ps); /* mutex */ for (i=0; i<ARP_TSIZE; ++i) { if ((pae = &arptable[i])->ae_state == AS_FREE) continue; if (pae->ae_ttl == ARP_INF) continue; /* don't time out permanent entry */ if ((pae->ae_ttl -= gran) <= 0) if (pae->ae_state == AS_RESOLVED) pae->ae_state = AS_FREE; else if (++pae->ae_attempts > ARP_MAXRETRY) { pae->ae_state = AS_FREE; arpdq(pae); } else { pae->ae_ttl = ARP_RESEND; arpsend(pae); } } restore(ps); }