diff --git a/ChangeLog b/ChangeLog index 1cfdfbb39a..9c9386b0c9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -260,4 +260,8 @@ 0.3.4 2007-xx-xx Gregory Nutt - * Added netutils/dhcpd + * Added and partially verified DHCP server logic (netutils/dhcpd) + * Fix BROADCAST=y compilation problems + * Fix UDP recvfrom timeout bug + * Correct processing of input UDP broadcast packets. + * Verfied basic DHCP client functionality (netutils/dhcpc) diff --git a/Documentation/NuttX.html b/Documentation/NuttX.html index 20a4a29eb8..e6fd36bdde 100644 --- a/Documentation/NuttX.html +++ b/Documentation/NuttX.html @@ -748,7 +748,11 @@ Other memory:
diff --git a/examples/uip/main.c b/examples/uip/main.c index a5640f848c..e2186b014e 100644 --- a/examples/uip/main.c +++ b/examples/uip/main.c @@ -187,10 +187,19 @@ int user_start(int argc, char *argv[]) { struct dhcpc_state ds; (void)dhcpc_request(handle, &ds); - uip_sethostaddr("eth0", &ds.ipaddr); - uip_setnetmask("eth0", &ds.netmask); - uip_setdraddr("eth0", &ds.default_router); - resolv_conf(&ds.dnsaddr); + uip_sethostaddr("eth1", &ds.ipaddr); + if (ds.netmask.s_addr != 0) + { + uip_setnetmask("eth0", &ds.netmask); + } + if (ds.default_router.s_addr != 0) + { + uip_setdraddr("eth0", &ds.default_router); + } + if (ds.dnsaddr.s_addr != 0) + { + resolv_conf(&ds.dnsaddr); + } dhcpc_close(handle); } #endif diff --git a/net/uip/uip-initialize.c b/net/uip/uip-initialize.c index decc60ff8b..9b51e17358 100644 --- a/net/uip/uip-initialize.c +++ b/net/uip/uip-initialize.c @@ -70,14 +70,14 @@ const uip_ipaddr_t g_alloneaddr = #ifdef CONFIG_NET_IPv6 {0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff}; #else - {0xffffffff}; + 0xffffffff; #endif const uip_ipaddr_t g_allzeroaddr = #ifdef CONFIG_NET_IPv6 {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}; #else - {0x00000000}; + 0x00000000; #endif /* Reassembly timer (units: deci-seconds) */ diff --git a/netutils/README b/netutils/README index 443b0636e5..6a7de07752 100644 --- a/netutils/README +++ b/netutils/README @@ -1,5 +1,20 @@ netutils ^^^^^^^^ -This directory contains most of the network applications contained under the uIP-1.0 apps directory. -As the uIP apps/README says, these applications "are not all heavily tested." +This directory contains most of the network applications contained +under the uIP-1.0 apps directory. As the uIP apps/README says, +these applications "are not all heavily tested." These uIP apps +include: + + dhcpc - Dynamic Host Configuration Protocol (DHCP) client + resolv - uIP DNS resolver + smtp - Simple Mail Transfer Protocol (SMTP) client + telnetd - TELNET server + webclient - HTTP web client + webserver - HTTP web server + +Additional applications that were not part of uIP (but which are +highly influenced by uIP) include: + + dhcpd - Dynamic Host Configuration Protocol (DHCP) server + diff --git a/netutils/dhcpc/dhcpc.c b/netutils/dhcpc/dhcpc.c index 0188128f29..e0ee702c22 100644 --- a/netutils/dhcpc/dhcpc.c +++ b/netutils/dhcpc/dhcpc.c @@ -183,18 +183,12 @@ static uint8 *add_end(uint8 *optptr) static void create_msg(struct dhcpc_state_s *pdhcpc) { - struct in_addr addr; - memset(&pdhcpc->packet, 0, sizeof(struct dhcp_msg)); pdhcpc->packet.op = DHCP_REQUEST; pdhcpc->packet.htype = DHCP_HTYPE_ETHERNET; pdhcpc->packet.hlen = pdhcpc->ds_maclen; memcpy(pdhcpc->packet.xid, xid, 4); pdhcpc->packet.flags = HTONS(BOOTP_BROADCAST); /* Broadcast bit. */ - - uip_gethostaddr("eth0", &addr); - memcpy(&pdhcpc->packet.ciaddr, &addr.s_addr, 4); - memcpy(pdhcpc->packet.chaddr, pdhcpc->ds_macaddr, pdhcpc->ds_maclen); memset(&pdhcpc->packet.chaddr[pdhcpc->ds_maclen], 0, 16 - pdhcpc->ds_maclen); memcpy(pdhcpc->packet.options, magic_cookie, sizeof(magic_cookie)); @@ -206,13 +200,20 @@ static int send_discover(struct dhcpc_state_s *pdhcpc) uint8 *pend; int len; + /* Create the basic message header */ + create_msg(pdhcpc); + + /* Add the options */ + pend = &pdhcpc->packet.options[4]; pend = add_msg_type(pend, DHCPDISCOVER); pend = add_req_options(pend); pend = add_end(pend); len = pend - (uint8*)&pdhcpc->packet; + /* Send the request */ + addr.sin_family = AF_INET; addr.sin_port = HTONS(DHCPC_SERVER_PORT); addr.sin_addr.s_addr = INADDR_BROADCAST; @@ -226,7 +227,13 @@ static int send_request(struct dhcpc_state_s *pdhcpc, struct dhcpc_state *presul uint8 *pend; int len; + /* Create the basic message header */ + create_msg(pdhcpc); + memcpy(pdhcpc->packet.ciaddr, &presult->ipaddr.s_addr, 4); + + /* Add the options */ + pend = &pdhcpc->packet.options[4]; pend = add_msg_type(pend, DHCPREQUEST); pend = add_server_id(presult, pend); @@ -234,6 +241,8 @@ static int send_request(struct dhcpc_state_s *pdhcpc, struct dhcpc_state *presul pend = add_end(pend); len = pend - (uint8*)&pdhcpc->packet; + /* Send the request */ + addr.sin_family = AF_INET; addr.sin_port = HTONS(DHCPC_SERVER_PORT); addr.sin_addr.s_addr = INADDR_BROADCAST; @@ -336,7 +345,7 @@ void *dhcpc_open(const void *macaddr, int maclen) /* Configure for read timeouts */ - tv.tv_sec = 30; + tv.tv_sec = 10; tv.tv_usec = 0; if (setsockopt(pdhcpc->sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(struct timeval)) < 0) { @@ -361,9 +370,15 @@ void dhcpc_close(void *handle) int dhcpc_request(void *handle, struct dhcpc_state *presult) { struct dhcpc_state_s *pdhcpc = (struct dhcpc_state_s *)handle; + struct in_addr oldaddr; ssize_t result; int state; + /* Save the currently assigned IP address (should be zero) */ + + oldaddr.s_addr = 0; + uip_gethostaddr("eth0", &oldaddr); + /* Loop until we receive the offer */ do @@ -386,6 +401,7 @@ int dhcpc_request(void *handle, struct dhcpc_state *presult) { if (parse_msg(pdhcpc, result, presult) == DHCPOFFER) { + (void)uip_sethostaddr("eth0", &presult->ipaddr); state = STATE_OFFER_RECEIVED; } } @@ -421,6 +437,7 @@ int dhcpc_request(void *handle, struct dhcpc_state *presult) { /* An error other than a timeout was received */ + (void)uip_sethostaddr("eth0", &oldaddr); return ERROR; } } diff --git a/netutils/dhcpd/dhcpd.c b/netutils/dhcpd/dhcpd.c index 331d945a92..f160dcc216 100644 --- a/netutils/dhcpd/dhcpd.c +++ b/netutils/dhcpd/dhcpd.c @@ -692,8 +692,8 @@ static inline int dhcpd_socket(void) int sockfd; #if defined(HAVE_SO_REUSEADDR) || defined(HAVE_SO_BROADCAST) int optval; -#endif int ret; +#endif /* Create a socket to listen for requests from DHCP clients */ @@ -815,6 +815,7 @@ static int dhcpd_sendpacket(int bbroadcast) struct sockaddr_in addr; in_addr_t ipaddr; int sockfd; + int len; int ret = ERROR; /* Determine which address to respond to (or if we need to broadcast the response) */ @@ -850,8 +851,10 @@ static int dhcpd_sendpacket(int bbroadcast) addr.sin_port = HTONS(DHCP_CLIENT_PORT); addr.sin_addr.s_addr = ipaddr; - ret = sendto(sockfd, - &g_state.ds_outpacket, sizeof(struct dhcpmsg_s), 0, + /* Send the minimum sized packet that includes the END option */ + + len = (g_state.ds_optend - (uint8*)&g_state.ds_outpacket) + 1; + ret = sendto(sockfd, &g_state.ds_outpacket, len, 0, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)); close(sockfd); } @@ -1031,9 +1034,8 @@ static inline int dhcpd_request(void) * already offered to the client. */ - if (g_state.ds_optserverip == g_state.ds_serverip && - g_state.ds_optreqip != 0 && - g_state.ds_optreqip == ipaddr) + if (g_state.ds_optserverip == ntohl(g_state.ds_serverip) && + (g_state.ds_optreqip != 0 || g_state.ds_optreqip == ipaddr)) { response = DHCPACK; } @@ -1278,6 +1280,12 @@ int dhcpd_run(void) continue; } +#ifdef CONFIG_NETUTILS_DHCPD_HOST + /* Get the poor little uC a change to get its recvfrom in place */ + + sleep(2); +#endif + /* Now process the incoming DHCP message by its message type */ switch (g_state.ds_optmsgtype)