static int ping_send(void) { uchar *pkt; int eth_hdr_size; /* XXX always send arp request */ debug_cond(DEBUG_DEV_PKT, "sending ARP for %pI4\n", &NetPingIP); NetArpWaitPacketIP = NetPingIP; eth_hdr_size = NetSetEther(NetTxPacket, NetEtherNullAddr, PROT_IP); pkt = (uchar *)NetTxPacket + eth_hdr_size; set_icmp_header(pkt, NetPingIP); /* size of the waiting packet */ NetArpWaitTxPacketSize = eth_hdr_size + IP_ICMP_HDR_SIZE; /* and do the ARP request */ NetArpWaitTry = 1; NetArpWaitTimerStart = get_timer(0); ArpRequest(); return 1; /* waiting */ }
// ------------------------------------------------------------------------------------------------ void EthSendIntf(NetIntf *intf, const void *dstAddr, u16 etherType, NetBuf *pkt) { // Determine ethernet address by protocol of packet const EthAddr *dstEthAddr = 0; switch (etherType) { case ET_ARP: dstEthAddr = (const EthAddr *)dstAddr; break; case ET_IPV4: { const Ipv4Addr *dstIpv4Addr = (const Ipv4Addr *)dstAddr; if (Ipv4AddrEq(dstIpv4Addr, &g_broadcastIpv4Addr) || Ipv4AddrEq(dstIpv4Addr, &intf->broadcastAddr)) { // IP Broadcast -> Ethernet Broacast dstEthAddr = &g_broadcastEthAddr; } else { // Lookup Ethernet address in ARP cache dstEthAddr = ArpLookupEthAddr(dstIpv4Addr); if (!dstEthAddr) { ArpRequest(intf, dstIpv4Addr, etherType, pkt); return; } } } break; case ET_IPV6: break; } // Skip packets without a destination if (!dstEthAddr) { ConsolePrint("Dropped packet\n"); return; } // Fill in ethernet header pkt->start -= sizeof(EthHeader); EthHeader *hdr = (EthHeader *)pkt->start; hdr->dst = *dstEthAddr; hdr->src = intf->ethAddr; hdr->etherType = NetSwap16(etherType); // Transmit EthPrint(pkt); intf->devSend(pkt); }
int NetSendUDPPacket(uchar *ether, IPaddr_t dest, int dport, int sport, int payload_len) { uchar *pkt; int eth_hdr_size; int pkt_hdr_size; /* make sure the NetTxPacket is initialized (NetInit() was called) */ assert(NetTxPacket != NULL); if (NetTxPacket == NULL) return -1; /* convert to new style broadcast */ if (dest == 0) dest = 0xFFFFFFFF; /* if broadcast, make the ether address a broadcast and don't do ARP */ if (dest == 0xFFFFFFFF) ether = NetBcastAddr; pkt = (uchar *)NetTxPacket; eth_hdr_size = NetSetEther(pkt, ether, PROT_IP); pkt += eth_hdr_size; net_set_udp_header(pkt, dest, dport, sport, payload_len); pkt_hdr_size = eth_hdr_size + IP_UDP_HDR_SIZE; /* if MAC address was not discovered yet, do an ARP request */ if (memcmp(ether, NetEtherNullAddr, 6) == 0) { debug_cond(DEBUG_DEV_PKT, "sending ARP for %pI4\n", &dest); /* save the ip and eth addr for the packet to send after arp */ NetArpWaitPacketIP = dest; NetArpWaitPacketMAC = ether; /* size of the waiting packet */ NetArpWaitTxPacketSize = pkt_hdr_size + payload_len; /* and do the ARP request */ NetArpWaitTry = 1; NetArpWaitTimerStart = get_timer(0); ArpRequest(); return 1; /* waiting */ } else { debug_cond(DEBUG_DEV_PKT, "sending UDP to %pI4/%pM\n", &dest, ether); NetSendPacket(NetTxPacket, pkt_hdr_size + payload_len); return 0; /* transmitted */ } }
void ArpTimeoutCheck(void) { ulong t; if (!NetArpWaitPacketIP) return; t = get_timer(0); /* check for arp timeout */ if ((t - NetArpWaitTimerStart) > ARP_TIMEOUT) { NetArpWaitTry++; if (NetArpWaitTry >= ARP_TIMEOUT_COUNT) { puts("\nARP Retry count exceeded; starting again\n"); NetArpWaitTry = 0; NetStartAgain(); } else { NetArpWaitTimerStart = t; ArpRequest(); } } }