📄 arp.c
字号:
buf->type = htons(RARP_TYPE); ni->broadcast(buf); } /*-------------------------------------------------------------------*/ /* Calculate next RARP timeout. */ /*-------------------------------------------------------------------*/ if (++RarpRetries > 5) RarpRetries = 0; timeout = (rand() % K2_SECONDS) + TICKS_PER_SEC * (3 + (1 << RarpRetries)); /*-------------------------------------------------------------------*/ /* Schedule next RARP request. */ /*-------------------------------------------------------------------*/ NetTimerStart(&RarpTimer, timeout);}/***********************************************************************//* find_entry: Search for matching ARP table entry *//* *//* Input: ip_addr = IP address to match *//* *//* Returns: pointer to ARP table entry or NULL *//* *//***********************************************************************/static ArpEntry *find_entry(ui32 ip_addr){ int i = 0; /*-------------------------------------------------------------------*/ /* Search through ARP table, resuming at the last entry found. */ /*-------------------------------------------------------------------*/ do { /*-----------------------------------------------------------------*/ /* Return entry pointer if IP addresses match and entry is valid. */ /*-----------------------------------------------------------------*/ if ((Entry->pr_addr == ip_addr) && (Entry->state != AES_FREE)) return Entry; /*-----------------------------------------------------------------*/ /* Increment entry pointer, wrapping when end is reached. */ /*-----------------------------------------------------------------*/ if (++Entry == &ArpTbl[ARP_TSIZE]) Entry = &ArpTbl[0]; } while (++i < ARP_TSIZE); /*-------------------------------------------------------------------*/ /* No match found. Return NULL. */ /*-------------------------------------------------------------------*/ return NULL;}/***********************************************************************//* add_entry: Initialize a new ARP cache entry *//* *//* Inputs: ni = pointer to network interface structure *//* arp = pointer to ARP packet *//* *//***********************************************************************/static void add_entry(Ni *ni, Arp *arp){ ArpEntry *arp_entry = alloc_entry(); arp_entry->ni = ni; memcpy(arp_entry->hw_addr, SenderHA(arp), arp->ha_len); memcpy(&arp_entry->pr_addr, SenderPA(arp), IP_ALEN); arp_entry->state = AES_RESOLVED; NetTimerStart(&arp_entry->timer, ARP_TIMEOUT);}/***********************************************************************//* alloc_entry: Select an ARP cache entry, deleting old if necessary *//* *//***********************************************************************/static ArpEntry *alloc_entry(void){ ArpEntry *entry; /*-------------------------------------------------------------------*/ /* Search ARP cache, starting at the oldest entry. */ /*-------------------------------------------------------------------*/ for (entry = OldestEntry;;) { /*-----------------------------------------------------------------*/ /* Allocate and return address if free entry is found. */ /*-----------------------------------------------------------------*/ if (entry->state == AES_FREE) { ++ArpCacheSize; entry->state = AES_PENDING; return entry; } /*-----------------------------------------------------------------*/ /* Increment entry pointer, wrapping around end. */ /*-----------------------------------------------------------------*/ if (++entry == &ArpTbl[ARP_TSIZE]) entry = &ArpTbl[0]; /*-----------------------------------------------------------------*/ /* If oldest entry is reached, reuse it. */ /*-----------------------------------------------------------------*/ if (entry == OldestEntry) { /*---------------------------------------------------------------*/ /* Free any pending outbound packets and set entry state. */ /*---------------------------------------------------------------*/ if (entry->qhead) free_queue(entry); entry->state = AES_PENDING; /*---------------------------------------------------------------*/ /* Advance oldest entry pointer. */ /*---------------------------------------------------------------*/ if (++OldestEntry == &ArpTbl[ARP_TSIZE]) OldestEntry = &ArpTbl[0]; /*---------------------------------------------------------------*/ /* Return pointer to entry. */ /*---------------------------------------------------------------*/ return entry; } }}/***********************************************************************//* free_queue: Free queue of expired ARP cache entries *//* *//* Input: arp_entry = pointer to ARP cache entry *//* *//***********************************************************************/static void free_queue(ArpEntry *arp_entry){ NetBuf *buf; while (arp_entry->qhead) { buf = arp_entry->qhead; arp_entry->qhead = arp_entry->qhead->next; tcpRetBuf(&buf); } arp_entry->qcount = 0;}/***********************************************************************//* send_request: Broadcast an ARP request *//* *//* Input: arp_entry = pointer to an ARP cache entry *//* *//***********************************************************************/static void send_request(ArpEntry *arp_entry){ Ni *ni = arp_entry->ni; int length = offsetof(Arp, addresses) + 2 * (IP_ALEN + ni->ha_len); NetBuf *buf; Arp *arp; /*-------------------------------------------------------------------*/ /* Request a network buffer, exiting if none free. */ /*-------------------------------------------------------------------*/ buf = tcpGetBuf(NIMHLEN + length); if (buf == NULL) return; /*-------------------------------------------------------------------*/ /* Schedule next resend and increment number of attempts. */ /*-------------------------------------------------------------------*/ NetTimerStart(&arp_entry->timer, ARP_RESEND); ++arp_entry->attempts; /*-------------------------------------------------------------------*/ /* Get pointer to packet frame and complete the ARP message fields. */ /*-------------------------------------------------------------------*/ arp = (Arp *)buf->ip_pkt; arp->hw_type = htons(ni->hw_type); arp->pr_type = htons(IP_TYPE); arp->ha_len = ni->ha_len; arp->pa_len = IP_ALEN; arp->operation = htons(ARP_REQUEST); memcpy(SenderHA(arp), ni->hw_addr, ni->ha_len); memcpy(SenderPA(arp), &ni->ip_addr, IP_ALEN); memset(TargetHA(arp), 0, ni->ha_len); memcpy(TargetPA(arp), &arp_entry->pr_addr, IP_ALEN);#if TCP_PROBE /*-------------------------------------------------------------------*/ /* Decode ARP packet if global decode flag is TRUE. */ /*-------------------------------------------------------------------*/ if (NetProbeFlag) got_arp(arp);#endif /*-------------------------------------------------------------------*/ /* Complete buffer data and request NI to transmit packet. */ /*-------------------------------------------------------------------*/ buf->length = length; buf->type = htons(ARP_TYPE); ni->broadcast(buf);}/***********************************************************************//* arp_reply: Send an ARP reply *//* *//* Inputs: ni = pointer to network interface *//* ha = pointer to target hardware address *//* pa = pointer to target protocol address *//* brdcst = broadcast if TRUE *//* *//***********************************************************************/static void arp_reply(const Ni *ni, ui8 *ha, ui8 *pa, int brdcst){ NetBuf *buf; Arp *reply; /*-------------------------------------------------------------------*/ /* Request a network buffer, exiting if none free. */ /*-------------------------------------------------------------------*/ buf = tcpGetBuf(NIMHLEN + offsetof(Arp, addresses) + 2 * (IP_ALEN + ni->ha_len)); if (buf == NULL) return; /*-------------------------------------------------------------------*/ /* Form ARP header. */ /*-------------------------------------------------------------------*/ reply = (Arp *)buf->ip_pkt; reply->hw_type = htons(ni->hw_type); reply->pr_type = htons(IP_TYPE); reply->ha_len = ni->ha_len; reply->pa_len = IP_ALEN; reply->operation = htons(ARP_REPLY); /*-------------------------------------------------------------------*/ /* Supply target addresses. */ /*-------------------------------------------------------------------*/ memcpy(TargetHA(reply), ha, ni->ha_len); memcpy(TargetPA(reply), pa, IP_ALEN); /*-------------------------------------------------------------------*/ /* Fill in sender's hardware and protocol addresses (ours). */ /*-------------------------------------------------------------------*/ memcpy(SenderHA(reply), ni->hw_addr, ni->ha_len); memcpy(SenderPA(reply), &ni->ip_addr, IP_ALEN);#if TCP_PROBE /*-------------------------------------------------------------------*/ /* Decode ARP packet if global decode flag is TRUE. */ /*-------------------------------------------------------------------*/ if (NetProbeFlag) got_arp(reply);#endif /*-------------------------------------------------------------------*/ /* Supply buffer header and request NI to send packet. */ /*-------------------------------------------------------------------*/ buf->length = offsetof(Arp, addresses) + 2 * (IP_ALEN + ni->ha_len); buf->type = htons(ARP_TYPE); if (brdcst) ni->broadcast(buf); else ni->transmit(buf, ha);}/***********************************************************************//* arp_timeout: Process ARP timeout *//* *//* Input: timer = pointer to expired ARP timer *//* *//***********************************************************************/static void arp_timeout(void *object){ ArpEntry *arp_entry = object; /*-------------------------------------------------------------------*/ /* If arp entry was resolved, set its state to free. */ /*-------------------------------------------------------------------*/ if (arp_entry->state == AES_RESOLVED) { arp_entry->state = AES_FREE; --ArpCacheSize; } /*-------------------------------------------------------------------*/ /* Else state was pending, free queue if max attempts exceeded. */ /*-------------------------------------------------------------------*/ else if (arp_entry->attempts > ARP_ATTEMPTS) { arp_entry->state = AES_FREE; free_queue(arp_entry); --ArpCacheSize; } /*-------------------------------------------------------------------*/ /* Else resend ARP request. */ /*-------------------------------------------------------------------*/ else send_request(arp_entry);}#if TCP_PROBE/***********************************************************************//* got_arp: Decode ARP/RARP requests and replies *//* *//***********************************************************************/static void got_arp(Arp *arp){ ui32 ip_addr; ui16 hw_type; ui16 pr_type; ui16 operation; char *op_str; /*-------------------------------------------------------------------*/ /* Convert ARP header fields to host byte order. */ /*-------------------------------------------------------------------*/ hw_type = ntohs(arp->hw_type); pr_type = ntohs(arp->pr_type); operation = ntohs(arp->operation); /*-------------------------------------------------------------------*/ /* Display ARP fields. */ /*-------------------------------------------------------------------*/ if (operation > 2) putchar('R'); printf("ARP: hw_type = %u, hw_len = %u\n", hw_type, arp->ha_len); if (operation > 2) putchar('R'); printf("ARP: pr_type = 0x%04X, pa_len = %u\n", pr_type, arp->pa_len); if (operation & 1) op_str = "REQUEST"; else op_str = "REPLY"; if (operation > 2) putchar('R'); printf("ARP: operation = %u (%s)\n", operation, op_str); memcpy(&ip_addr, SenderPA(arp), IP_ALEN); if (operation > 2) putchar('R'); printf("ARP: sender PA = "); printIP(ip_addr); putchar('\n'); if (operation > 2) putchar('R'); printf("ARP: sender HA = "); printEth(SenderHA(arp)); memcpy(&ip_addr, TargetPA(arp), IP_ALEN); putchar('\n'); if (operation > 2) putchar('R'); printf("ARP: target PA = "); printIP(ip_addr); putchar('\n'); if (operation > 2) putchar('R'); printf("ARP: target HA = "); printEth(TargetHA(arp)); printf("\n\n");}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -