Mercurial > ecos-v3_0-branch
diff packages/redboot/current/src/net/ip.c @ 115:6ed91473a1cd ecos-sw-2000-08-21
Merge from eCos master repository on 2000-08-21-22:40:54-BST
| author | jlarmour |
|---|---|
| date | Fri, 25 Aug 2000 17:32:38 +0000 |
| parents | |
| children | d63db767121d |
line wrap: on
line diff
new file mode 100644 --- /dev/null +++ b/packages/redboot/current/src/net/ip.c @@ -0,0 +1,177 @@ +//========================================================================== +// +// net/ip.c +// +// Stand-alone IP networking support for RedBoot +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-07-14 +// Purpose: +// Description: +// +// This code is part of RedBoot (tm). +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include <net/net.h> + +ip_addr_t __local_ip_addr = { 0, 0, 0, 0 }; + +static word ip_ident; + + +/* + * 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) + return 1; + + if (!memcmp(addr, __local_ip_addr, sizeof(ip_addr_t))) + return 1; + + /* + * Consider it an address match if we haven't gotten our IP address yet. + * Some DHCP servers will address IP packets to the assigned address + * instead of a IP broadcast address. + */ + if (__local_ip_addr[0] == 0 && __local_ip_addr[1] == 0 && + __local_ip_addr[2] == 0 && __local_ip_addr[3] == 0) + return 1; + + return 0; +} + + +extern void __tcp_handler(pktbuf_t *, ip_route_t *); + +/* + * Handle IP packets coming from the polled ethernet interface. + */ +void +__ip_handler(pktbuf_t *pkt, enet_addr_t *src_enet_addr) +{ + ip_header_t *ip = pkt->ip_hdr; + ip_route_t r; + int hdr_bytes; + + /* first make sure its ours and has a good checksum. */ + if (!ip_addr_match(ip->destination) || + __sum((word *)ip, ip->hdr_len << 2, 0) != 0) { + __pktbuf_free(pkt); + return; + } + + memcpy(r.ip_addr, ip->source, sizeof(ip_addr_t)); + memcpy(r.enet_addr, src_enet_addr, sizeof(enet_addr_t)); + + hdr_bytes = ip->hdr_len << 2; + pkt->pkt_bytes = ntohs(ip->length) - hdr_bytes; + + switch (ip->protocol) { + +#if NET_SUPPORT_ICMP + case IP_PROTO_ICMP: + pkt->icmp_hdr = (icmp_header_t *)(((char *)ip) + hdr_bytes); + __icmp_handler(pkt, &r); + break; +#endif + +#if NET_SUPPORT_TCP + case IP_PROTO_TCP: + pkt->tcp_hdr = (tcp_header_t *)(((char *)ip) + hdr_bytes); + __tcp_handler(pkt, &r); + break; +#endif + +#if NET_SUPPORT_UDP + case IP_PROTO_UDP: + pkt->udp_hdr = (udp_header_t *)(((char *)ip) + hdr_bytes); + __udp_handler(pkt, &r); + break; +#endif + + default: + __pktbuf_free(pkt); + break; + } +} + + +/* + * 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 +__ip_send(pktbuf_t *pkt, int protocol, ip_route_t *dest) +{ + ip_header_t *ip = pkt->ip_hdr; + int hdr_bytes; + unsigned short cksum; + + /* + * 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; + + ip->version = 4; + ip->hdr_len = hdr_bytes >> 2; + ip->tos = 0; + ip->length = htons(pkt->pkt_bytes); + ip->ident = htons(ip_ident); + ip_ident++; + ip->fragment = 0; + 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); +} + +
