Index: ip.c =================================================================== RCS file: /cvs/ecos/ecos/packages/redboot/current/src/net/ip.c,v retrieving revision 1.1 diff -U9 -r1.1 ip.c --- ip.c 25 Aug 2000 17:33:47 -0000 1.1 +++ ip.c 8 Jul 2002 18:18:36 -0000 @@ -37,24 +37,38 @@ // Purpose: // Description: // // This code is part of RedBoot (tm). // //####DESCRIPTIONEND#### // //========================================================================== +#include #include ip_addr_t __local_ip_addr = { 0, 0, 0, 0 }; +ip_addr_t __local_ip_mask = { 0, 0, 0, 0 }; +ip_addr_t __local_ip_gate = { 0, 0, 0, 0 }; + +extern int terseMode; static word ip_ident; +int __ip_addr_local(ip_addr_t *addr) +{ + return !( + ((__local_ip_addr[0] ^ (*addr)[0]) & __local_ip_mask[0]) | + ((__local_ip_addr[1] ^ (*addr)[1]) & __local_ip_mask[1]) | + ((__local_ip_addr[2] ^ (*addr)[2]) & __local_ip_mask[2]) | + ((__local_ip_addr[3] ^ (*addr)[3]) & __local_ip_mask[3])); +} + /* * Match given IP address to our address. * Check for broadcast matches as well. */ static int ip_addr_match(ip_addr_t addr) { if (addr[0] == 255 && addr[1] == 255 && addr[2] == 255 && addr[3] == 255) @@ -133,24 +147,25 @@ /* * Send an IP packet. * * The IP data field should contain pkt->pkt_bytes of data. * pkt->[udp|tcp|icmp]_hdr points to the IP data field. Any * IP options are assumed to be already in place in the IP * options field. */ -void +int __ip_send(pktbuf_t *pkt, int protocol, ip_route_t *dest) { ip_header_t *ip = pkt->ip_hdr; int hdr_bytes; unsigned short cksum; + ip_route_t destrt; /* * Figure out header length. The use udp_hdr is * somewhat arbitrary, but works because it is * a union with other IP protocol headers. */ hdr_bytes = (((char *)pkt->udp_hdr) - ((char *)ip)); pkt->pkt_bytes += hdr_bytes; @@ -165,13 +180,30 @@ ip->ttl = 255; ip->ttl = 64; ip->protocol = protocol; ip->checksum = 0; memcpy(ip->source, __local_ip_addr, sizeof(ip_addr_t)); memcpy(ip->destination, dest->ip_addr, sizeof(ip_addr_t)); cksum = __sum((word *)ip, hdr_bytes, 0); ip->checksum = htons(cksum); - __enet_send(pkt, &dest->enet_addr, ETH_TYPE_IP); + if ((dest->ip_addr[0] & dest->ip_addr[1] & dest->ip_addr[2]) == 255) { + memset(destrt.enet_addr,0xff,sizeof destrt.enet_addr); + } else if (__ip_addr_local((ip_addr_t *)&dest->ip_addr)) { + // local IP address -- look up Ethernet address in ARP cache + if (__arp_lookup(&dest->ip_addr, &destrt) < 0) { + if (!terseMode) printf("%s: Can't find address of server\n", __FUNCTION__); + return -1; + } + } else { + // non-local IP address -- look up Gateway's Ethernet address + if (__arp_lookup(&__local_ip_gate, &destrt) < 0) { + if (!terseMode) printf("%s: Can't find address of gateway\n", __FUNCTION__); + return -1; + } + } + + __enet_send(pkt, &destrt.enet_addr, ETH_TYPE_IP); + return 0; }