From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 15803 invoked by alias); 8 Jul 2002 18:47:39 -0000 Mailing-List: contact ecos-discuss-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: ecos-discuss-owner@sources.redhat.com Received: (qmail 15792 invoked from network); 8 Jul 2002 18:47:35 -0000 Received: from unknown (HELO conn.mc.mpls.visi.com) (208.42.156.2) by sources.redhat.com with SMTP; 8 Jul 2002 18:47:35 -0000 Received: from grante.comtrol.com (isis.visi.com [209.98.98.8]) by conn.mc.mpls.visi.com (Postfix) with SMTP id 962528224 for ; Mon, 8 Jul 2002 13:47:34 -0500 (CDT) Received: (qmail 30436 invoked by uid 500); 8 Jul 2002 18:51:07 -0000 Date: Mon, 08 Jul 2002 11:47:00 -0000 From: Grant Edwards To: todd.kallam@acterna.com Cc: ecos-discuss@sources.redhat.com Message-ID: <20020708135106.A30396@visi.com> References: <85256BF0.0062039C.00@wg.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="YZ5djTAD1cGYuMQK" Content-Disposition: inline User-Agent: Mutt/1.2i In-Reply-To: <85256BF0.0062039C.00@wg.com>; from todd.kallam@acterna.com on Mon, Jul 08, 2002 at 01:48:57PM -0400 Subject: Re: [ECOS] Redboot DHCP and gateway support X-SW-Source: 2002-07/txt/msg00076.txt.bz2 --YZ5djTAD1cGYuMQK Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-length: 673 > I am also interested in DHCP/Gateway support for Redboot. > I would like to get your patch or have support added to > the Redboot source if it is not already there. I've attached patches containing my DHCP and default route changes. Disclaimer: These patches are against a rather old version of Redboot (circa December 2000). Though I've tried to cull out extraneous diffs, I've made a lot of changes unrelated to DHCP/gateway, and these patches may contain unrelated changes that may or may not have already been incorporated into the CVS source tree (changes that you may or may not want). IOW, don't apply the patches blindly. -- Grant Edwards grante@visi.com --YZ5djTAD1cGYuMQK Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="bootp.h.patch" Content-length: 940 Index: bootp.h =================================================================== RCS file: /cvs/ecos/ecos/packages/redboot/current/include/net/bootp.h,v retrieving revision 1.1 diff -U8 -r1.1 bootp.h --- bootp.h 25 Aug 2000 17:33:46 -0000 1.1 +++ bootp.h 8 Jul 2002 18:36:22 -0000 @@ -74,17 +74,17 @@ * This file specifies the "implementation-independent" BOOTP protocol * information which is common to both client and server. * */ #define BP_CHADDR_LEN 16 #define BP_SNAME_LEN 64 #define BP_FILE_LEN 128 -#define BP_VEND_LEN 64 +#define BP_VEND_LEN 312 #define BP_MINPKTSZ 300 /* to check sizeof(struct bootp) */ typedef struct bootp { unsigned char bp_op; /* packet opcode type */ unsigned char bp_htype; /* hardware addr type */ unsigned char bp_hlen; /* hardware addr length */ unsigned char bp_hops; /* gateway hops */ unsigned int bp_xid; /* transaction ID */ --YZ5djTAD1cGYuMQK Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="net.h.patch" Content-length: 4565 Index: net.h =================================================================== RCS file: /cvs/ecos/ecos/packages/redboot/current/include/net/net.h,v retrieving revision 1.3 diff -U8 -r1.3 net.h --- net.h 8 Dec 2000 03:30:08 -0000 1.3 +++ net.h 8 Jul 2002 18:39:49 -0000 @@ -48,17 +48,19 @@ #include #include #include extern bool net_debug; extern unsigned long do_ms_tick(void); -#define MS_TICKS() do_ms_tick() +extern unsigned long get_ms_ticks(void); +#define MS_TICKS() get_ms_ticks() +#define MS_TICKS_DELAY() do_ms_tick() /* #define NET_SUPPORT_RARP 1 */ #define NET_SUPPORT_ICMP 1 #define NET_SUPPORT_UDP 1 #define NET_SUPPORT_TCP 1 #if (CYG_BYTEORDER == CYG_LSBFIRST) #ifndef __LITTLE_ENDIAN__ @@ -74,16 +76,17 @@ #define htonl(x) ntohl(x) #define htons(x) ntohs(x) /* * Minimum ethernet packet length. */ #define ETH_MIN_PKTLEN 60 #define ETH_MAX_PKTLEN 1514 +#define ETH_HDR_SIZE 14 typedef unsigned char enet_addr_t[6]; typedef unsigned char ip_addr_t[4]; typedef unsigned char octet; typedef unsigned short word; typedef unsigned int dword; @@ -160,17 +163,17 @@ #define RARP_REPLY 4 enet_addr_t sender_enet; ip_addr_t sender_ip; enet_addr_t target_enet; ip_addr_t target_ip; } arp_header_t; -#define ARP_PKT_SIZE (sizeof(arp_header_t) + sizeof(eth_header_t)) +#define ARP_PKT_SIZE (sizeof(arp_header_t) + ETH_HDR_SIZE) /* * Internet Protocol header. */ typedef struct { #ifdef __LITTLE_ENDIAN__ octet hdr_len:4, version:4; @@ -188,17 +191,17 @@ #define IP_PROTO_TCP 6 #define IP_PROTO_UDP 17 word checksum; ip_addr_t source; ip_addr_t destination; } ip_header_t; -#define IP_PKT_SIZE (60 + sizeof(eth_header_t)) +#define IP_PKT_SIZE (60 + ETH_HDR_SIZE) /* * A IP<->ethernet address mapping. */ typedef struct { ip_addr_t ip_addr; enet_addr_t enet_addr; @@ -255,19 +258,17 @@ word checksum; word ident; word seqnum; } icmp_header_t; typedef struct _pktbuf { struct _pktbuf *next; -#if 0 eth_header_t *eth_hdr; /* pointer to ethernet header */ -#endif union { ip_header_t *__iphdr; /* pointer to IP header */ arp_header_t *__arphdr; /* pointer to ARP header */ } u1; #define ip_hdr u1.__iphdr #define arp_hdr u1.__arphdr union { udp_header_t *__udphdr; /* pointer to UDP header */ @@ -330,17 +331,18 @@ char pktbuf[ETH_MAX_PKTLEN]; } tcp_socket_t; /* * Our address. */ extern enet_addr_t __local_enet_addr; extern ip_addr_t __local_ip_addr; - +extern ip_addr_t __local_ip_gate; +extern ip_addr_t __local_ip_mask; /* * Set a timer. Caller is responsible for providing the timer_t struct. */ extern void __timer_set(timer_t *t, unsigned long delay, tmr_handler_t handler, void *user_data); /* @@ -393,16 +395,21 @@ */ extern void __enet_poll(void); /* * Send an ethernet packet. */ extern void __enet_send(pktbuf_t *pkt, enet_addr_t *dest, int eth_type); +/* + * return true if addr is on local subnet + */ +extern int __ip_addr_local(ip_addr_t *addr); + /* * Handle incoming ARP packets. */ extern void __arp_handler(pktbuf_t *pkt); /* * Find the ethernet address of the machine with the given @@ -437,19 +444,19 @@ extern void __ip_handler(pktbuf_t *pkt, enet_addr_t *src_enet_addr); /* * 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. + * options field. Returns 0 for success. */ -extern void __ip_send(pktbuf_t *pkt, int protocol, ip_route_t *dest); +extern int __ip_send(pktbuf_t *pkt, int protocol, ip_route_t *dest); /* * Handle incoming ICMP packets. */ extern void __icmp_handler(pktbuf_t *pkt, ip_route_t *r); /* @@ -468,17 +475,17 @@ /* * Remove the handler for the given socket. */ extern void __udp_remove_listener(word port); /* * Send a UDP packet. */ -extern void __udp_send(char *buf, int len, ip_route_t *dest_ip, +extern int __udp_send(char *buf, int len, ip_route_t *dest_ip, word dest_port, word src_port); // Send a UDP packet extern int __udp_sendto(char *buf, int len, struct sockaddr_in *server, struct sockaddr_in *local); // Receive a UDP packet extern int __udp_recvfrom(char *buf, int len, --YZ5djTAD1cGYuMQK Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="bootp.c.patch" Content-length: 4676 Index: bootp.c =================================================================== RCS file: /cvs/ecos/ecos/packages/redboot/current/src/net/bootp.c,v retrieving revision 1.1 diff -U9 -r1.1 bootp.c --- bootp.c 25 Aug 2000 17:33:47 -0000 1.1 +++ bootp.c 8 Jul 2002 18:17:17 -0000 @@ -49,95 +49,147 @@ extern int net_debug; #define SHOULD_BE_RANDOM 0x12345555 /* How many milliseconds to wait before retrying the request */ #define RETRY_TIME 2000 static bootp_header_t *bp_info; +static const unsigned char dhcpCookie[] = {99,130,83,99}; +static const unsigned char dhcpEndOption[] = {255}; +static const unsigned char dhcpRequestOption[] = {52,1,3}; + +void dump_buf(void *p, CYG_ADDRWORD s); + static void bootp_handler(udp_socket_t *skt, char *buf, int len, - ip_route_t *src_route, word src_port) + ip_route_t *src_route, word src_port) { bootp_header_t *b; - + unsigned char *p,*end; + int optlen; + b = (bootp_header_t *)buf; + if (bp_info) { + memset(bp_info,0,sizeof *bp_info); + if (len > sizeof *bp_info) + len = sizeof *bp_info; memcpy(bp_info, b, len); } - - if (b->bp_op == BOOTREPLY && - !memcmp(b->bp_chaddr, __local_enet_addr, 6)) { - memcpy(__local_ip_addr, &b->bp_yiaddr, 4); + + if (b->bp_op != BOOTREPLY) + return; + + if (memcmp(b->bp_chaddr, __local_enet_addr, 6)) + return; + + memcpy(__local_ip_addr, &b->bp_yiaddr, 4); + memcpy(__local_ip_gate, &b->bp_giaddr, 4); + + if (memcmp(b->bp_vend,dhcpCookie,sizeof dhcpCookie)) + return; + + optlen = len - (b->bp_vend - ((unsigned char*)b)); + + p = b->bp_vend+4; + end = ((unsigned char*)b) + len; + + while (p < end) { + unsigned char tag = *p; + if (tag == 255) + break; + if (tag == 0) + optlen = 1; + else { + optlen = p[1]; + p += 2; + switch (tag) { + case 1: // subnet mask + memcpy(__local_ip_mask,p,4); + break; + case 3: // router + memcpy(__local_ip_gate,p,4); + break; + default: + break; + } + } + p += optlen; } } +#define AddOption(p,d) do {memcpy(p,d,sizeof d); p += sizeof d;} while (0) /* * Find our IP address and copy to __local_ip_addr. * Return zero if successful, -1 if not. */ int __bootp_find_local_ip(bootp_header_t *info) { udp_socket_t udp_skt; bootp_header_t b; ip_route_t r; int retry; unsigned long start; + unsigned char *p; + int txSize; bp_info = info; memset(&b, 0, sizeof(b)); b.bp_op = BOOTREQUEST; b.bp_htype = HTYPE_ETHERNET; b.bp_hlen = 6; b.bp_xid = SHOULD_BE_RANDOM; - + + p = b.bp_vend; + + AddOption(p,dhcpCookie); + AddOption(p,dhcpRequestOption); + AddOption(p,dhcpEndOption); + + txSize = p - (unsigned char*)&b; + __local_ip_addr[0] = 0; __local_ip_addr[1] = 0; __local_ip_addr[2] = 0; __local_ip_addr[3] = 0; memcpy(b.bp_chaddr, __local_enet_addr, 6); /* fill out route for a broadcast */ r.ip_addr[0] = 255; r.ip_addr[1] = 255; r.ip_addr[2] = 255; r.ip_addr[3] = 255; - r.enet_addr[0] = 255; - r.enet_addr[1] = 255; - r.enet_addr[2] = 255; - r.enet_addr[3] = 255; - r.enet_addr[4] = 255; - r.enet_addr[5] = 255; /* setup a socket listener for bootp replies */ __udp_install_listener(&udp_skt, IPPORT_BOOTPC, bootp_handler); retry = 3; while (retry-- > 0) { - start = MS_TICKS(); - - __udp_send((char *)&b, sizeof(b), &r, IPPORT_BOOTPS, IPPORT_BOOTPC); - - do { - __enet_poll(); - if (__local_ip_addr[0] || __local_ip_addr[1] || - __local_ip_addr[2] || __local_ip_addr[3]) { - /* success */ - __udp_remove_listener(IPPORT_BOOTPC); - return 0; - } - } while ((MS_TICKS() - start) < RETRY_TIME); + start = MS_TICKS(); + + __udp_send((char *)&b, txSize, &r, IPPORT_BOOTPS, IPPORT_BOOTPC); + + do { + __enet_poll(); + if (__local_ip_addr[0] || __local_ip_addr[1] || + __local_ip_addr[2] || __local_ip_addr[3]) { + /* success */ + __udp_remove_listener(IPPORT_BOOTPC); + return 0; + } + } while ((MS_TICKS_DELAY() - start) < RETRY_TIME); } - + /* timed out */ __udp_remove_listener(IPPORT_BOOTPC); net_debug = 0; return -1; } --YZ5djTAD1cGYuMQK Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="ip.c.patch" Content-length: 3164 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; } --YZ5djTAD1cGYuMQK Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="udp.c.patch" Content-length: 2900 Index: udp.c =================================================================== RCS file: /cvs/ecos/ecos/packages/redboot/current/src/net/udp.c,v retrieving revision 1.2 diff -U9 -r1.2 udp.c --- udp.c 31 Oct 2000 20:53:15 -0000 1.2 +++ udp.c 8 Jul 2002 18:19:33 -0000 @@ -47,19 +47,19 @@ #include #ifdef UDP_STATS static int udp_rx_total; static int udp_rx_handled; static int udp_rx_cksum; static int udp_rx_dropped; #endif -#define MAX_UDP_DATA (ETH_MAX_PKTLEN - (sizeof(eth_header_t) + \ +#define MAX_UDP_DATA (ETH_MAX_PKTLEN - (ETH_HDR_SIZE + \ sizeof(ip_header_t) + \ sizeof(udp_header_t))) /* * A major assumption is that only a very small number of sockets will * active, so a simple linear search of those sockets is acceptible. */ static udp_socket_t *udp_list; @@ -136,35 +136,35 @@ } } __pktbuf_free(pkt); } /* * Send a UDP packet. */ -void +int __udp_send(char *buf, int len, ip_route_t *dest_ip, word dest_port, word src_port) { pktbuf_t *pkt; udp_header_t *udp; ip_header_t *ip; unsigned short cksum; - + int ret; /* dumb */ if (len > MAX_UDP_DATA) - return; + return -1; /* just drop it if can't get a buffer */ if ((pkt = __pktbuf_alloc(ETH_MAX_PKTLEN)) == NULL) - return; + return -1; udp = pkt->udp_hdr; ip = pkt->ip_hdr; pkt->pkt_bytes = len + sizeof(udp_header_t); udp->src_port = htons(src_port); udp->dest_port = htons(dest_port); udp->length = htons(pkt->pkt_bytes); @@ -175,36 +175,31 @@ /* fill in some pseudo-header fields */ memcpy(ip->source, __local_ip_addr, sizeof(ip_addr_t)); memcpy(ip->destination, dest_ip->ip_addr, sizeof(ip_addr_t)); ip->protocol = IP_PROTO_UDP; ip->length = udp->length; cksum = __sum((word *)udp, pkt->pkt_bytes, __pseudo_sum(ip)); udp->checksum = htons(cksum); - __ip_send(pkt, IP_PROTO_UDP, dest_ip); - + ret = __ip_send(pkt, IP_PROTO_UDP, dest_ip); __pktbuf_free(pkt); + + return ret; } int __udp_sendto(char *data, int len, struct sockaddr_in *server, struct sockaddr_in *local) { ip_route_t rt; - - if (__arp_lookup((ip_addr_t *)&server->sin_addr, &rt) < 0) { - printf("%s: Can't find address of server\n", __FUNCTION__); - return -1; - } else { - __udp_send(data, len, &rt, ntohs(server->sin_port), ntohs(local->sin_port)); - return 0; - } + memcpy(rt.ip_addr,&(server->sin_addr),sizeof rt.ip_addr); + return __udp_send(data, len, &rt, ntohs(server->sin_port), ntohs(local->sin_port)); } static char *recvfrom_buf; static int recvfrom_len; static struct sockaddr_in *recvfrom_server; static void __udp_recvfrom_handler(udp_socket_t *skt, char *buf, int len, ip_route_t *src_route, word src_port) --YZ5djTAD1cGYuMQK Content-Type: text/plain; charset=us-ascii Content-length: 146 -- Before posting, please read the FAQ: http://sources.redhat.com/fom/ecos and search the list archive: http://sources.redhat.com/ml/ecos-discuss --YZ5djTAD1cGYuMQK--