diff --git a/examples/dhcpd/host.c b/examples/dhcpd/host.c index 479a845c1..d66170fa6 100644 --- a/examples/dhcpd/host.c +++ b/examples/dhcpd/host.c @@ -37,6 +37,9 @@ * Included Files ****************************************************************************/ +#include +#include + /**************************************************************************** * Private Data ****************************************************************************/ @@ -45,7 +48,7 @@ * Public Functions ****************************************************************************/ -extern int dhcpd_run(void); +extern int dhcpd_run(const char *interface); /**************************************************************************** * main @@ -53,6 +56,16 @@ extern int dhcpd_run(void); int main(int argc, char **argv, char **envp) { - dhcpd_run(); + /* One and only one argument is expected: The network device name. */ + + if (argc != 2) + { + fprintf(stderr, "ERROR: Invalid number of arguments\n"); + fprintf(stderr, "Usage: %s \n", argv[0]); + exit(EXIT_FAILURE); + } + + dhcpd_run(argv[1]); + return 0; } diff --git a/examples/dhcpd/target.c b/examples/dhcpd/target.c index 10f0cc619..64c11394c 100644 --- a/examples/dhcpd/target.c +++ b/examples/dhcpd/target.c @@ -1,7 +1,7 @@ /**************************************************************************** * examples/dhcpd/target.c * - * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved. + * Copyright (C) 2009, 2011, 2020 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -40,6 +40,7 @@ #include #include +#include #include #include #include @@ -52,6 +53,7 @@ ****************************************************************************/ /* Configuation Checkes *****************************************************/ + /* BEWARE: * There are other configuration settings needed in netutils/dhcpd/dhcpdc.c, * but there are default values for those so we cannot check them here. @@ -82,7 +84,21 @@ #endif /**************************************************************************** - * Private Data + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * dhcpd_showusage + ****************************************************************************/ + +static void dhcpd_showusage(FAR const char *progname, int exitcode) +{ + fprintf(stderr, "Usage: %s \n", progname); + exit(exitcode); +} + +/**************************************************************************** + * Public Functions ****************************************************************************/ /**************************************************************************** @@ -91,12 +107,23 @@ int main(int argc, FAR char *argv[]) { + FAR const char *devname; struct in_addr addr; #if defined(CONFIG_EXAMPLES_DHCPD_NOMAC) uint8_t mac[IFHWADDRLEN]; #endif -/* Many embedded network interfaces must have a software assigned MAC */ + /* One and only one argument is expected: The network device name. */ + + if (argc != 2) + { + fprintf(stderr, "ERROR: Invalid number of arguments\n"); + dhcpd_showusage(argv[0], EXIT_FAILURE); + } + + devname = argv[1]; + + /* Many embedded network interfaces must have a software assigned MAC */ #ifdef CONFIG_EXAMPLES_DHCPD_NOMAC mac[0] = 0x00; @@ -105,32 +132,32 @@ int main(int argc, FAR char *argv[]) mac[3] = 0xad; mac[4] = 0xbe; mac[5] = 0xef; - netlib_setmacaddr("eth0", mac); + netlib_setmacaddr(devname, mac); #endif /* Set up our host address */ addr.s_addr = HTONL(CONFIG_EXAMPLES_DHCPD_IPADDR); - netlib_set_ipv4addr("eth0", &addr); + netlib_set_ipv4addr(devname, &addr); /* Set up the default router address */ addr.s_addr = HTONL(CONFIG_EXAMPLES_DHCPD_DRIPADDR); - netlib_set_dripv4addr("eth0", &addr); + netlib_set_dripv4addr(devname, &addr); /* Setup the subnet mask */ addr.s_addr = HTONL(CONFIG_EXAMPLES_DHCPD_NETMASK); - netlib_set_ipv4netmask("eth0", &addr); + netlib_set_ipv4netmask(devname, &addr); /* New versions of netlib_set_ipvXaddr will not bring the network up, * So ensure the network is really up at this point. */ - netlib_ifup("eth0"); + netlib_ifup(devname); /* Then start the server */ - dhcpd_run(); + dhcpd_run(devname); return 0; } diff --git a/include/netutils/dhcpd.h b/include/netutils/dhcpd.h index 3e36410fe..089aa468e 100644 --- a/include/netutils/dhcpd.h +++ b/include/netutils/dhcpd.h @@ -62,7 +62,7 @@ extern "C" #define EXTERN extern #endif -int dhcpd_run(void); +int dhcpd_run(FAR const char *interface); #undef EXTERN #ifdef __cplusplus diff --git a/netutils/dhcpd/Kconfig b/netutils/dhcpd/Kconfig index a10e77e92..9f6e4c76e 100644 --- a/netutils/dhcpd/Kconfig +++ b/netutils/dhcpd/Kconfig @@ -32,10 +32,6 @@ config NETUTILS_DHCPD_IGNOREBROADCAST cause the server to ignore the client broadcast flag and always respond with multicast; the value 0 to allows clients to request unicast. -config NETUTILS_DHCPD_INTERFACE - string "DHCPD network interface" - default "eth0" - config NETUTILS_DHCPD_LEASETIME int "Lease time (seconds)" default 864000 diff --git a/netutils/dhcpd/dhcpd.c b/netutils/dhcpd/dhcpd.c index 16c7a36e2..69f1e053b 100644 --- a/netutils/dhcpd/dhcpd.c +++ b/netutils/dhcpd/dhcpd.c @@ -1,7 +1,8 @@ /**************************************************************************** * netutils/dhcpd/dhcpd.c * - * Copyright (C) 2007-2009, 2011-2014, 2017 Gregory Nutt. All rights reserved. + * Copyright (C) 2007-2009, 2011-2014, 2017, 2020 Gregory Nutt. All rights + * reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -159,10 +160,6 @@ # define CONFIG_NETUTILS_DHCPD_MAXLEASETIME (60*60*24*30) /* 30 days */ #endif -#ifndef CONFIG_NETUTILS_DHCPD_INTERFACE -# define CONFIG_NETUTILS_DHCPD_INTERFACE "eth0" -#endif - #ifndef CONFIG_NETUTILS_DHCPD_MAXLEASES # define CONFIG_NETUTILS_DHCPD_MAXLEASES 16 #endif @@ -273,8 +270,11 @@ struct dhcpd_state_s * Private Data ****************************************************************************/ -static const uint8_t g_magiccookie[4] = {99, 130, 83, 99}; -static const uint8_t g_anyipaddr[4] = {0, 0, 0, 0}; +static const uint8_t g_magiccookie[4] = +{ + 99, 130, 83, 99 +}; + static struct dhcpd_state_s g_state; /**************************************************************************** @@ -386,7 +386,7 @@ struct lease_s *dhcpd_setlease(const uint8_t *mac, in_addr_t ipaddr, time_t expi * Name: dhcp_leaseipaddr ****************************************************************************/ -static inline in_addr_t dhcp_leaseipaddr(struct lease_s *lease) +static inline in_addr_t dhcp_leaseipaddr(FAR struct lease_s *lease) { /* Return IP address in host order */ @@ -397,7 +397,7 @@ static inline in_addr_t dhcp_leaseipaddr(struct lease_s *lease) * Name: dhcpd_findbymac ****************************************************************************/ -static struct lease_s *dhcpd_findbymac(const uint8_t *mac) +static FAR struct lease_s *dhcpd_findbymac(FAR const uint8_t *mac) { int i; @@ -416,12 +416,13 @@ static struct lease_s *dhcpd_findbymac(const uint8_t *mac) * Name: dhcpd_findbyipaddr ****************************************************************************/ -static struct lease_s *dhcpd_findbyipaddr(in_addr_t ipaddr) +static FAR struct lease_s *dhcpd_findbyipaddr(in_addr_t ipaddr) { if (ipaddr >= CONFIG_NETUTILS_DHCPD_STARTIP && ipaddr <= CONFIG_NETUTILS_DHCP_OPTION_ENDIP) { - struct lease_s *lease = &g_state.ds_leases[ipaddr - CONFIG_NETUTILS_DHCPD_STARTIP]; + FAR struct lease_s *lease = + &g_state.ds_leases[ipaddr - CONFIG_NETUTILS_DHCPD_STARTIP]; if (lease->allocated > 0) { return lease; @@ -459,10 +460,12 @@ static in_addr_t dhcpd_allocipaddr(void) # warning "FIXME: Should check if anything responds to an ARP request or ping" # warning " to verify that there is no other user of this IP address" #endif - memset(g_state.ds_leases[ipaddr - CONFIG_NETUTILS_DHCPD_STARTIP].mac, 0, DHCP_HLEN_ETHERNET); + memset(g_state.ds_leases[ipaddr - CONFIG_NETUTILS_DHCPD_STARTIP].mac, 0, + DHCP_HLEN_ETHERNET); g_state.ds_leases[ipaddr - CONFIG_NETUTILS_DHCPD_STARTIP].allocated = true; #ifdef HAVE_LEASE_TIME - g_state.ds_leases[ipaddr - CONFIG_NETUTILS_DHCPD_STARTIP].expiry = dhcpd_time() + CONFIG_NETUTILS_DHCPD_OFFERTIME; + g_state.ds_leases[ipaddr - CONFIG_NETUTILS_DHCPD_STARTIP].expiry = + dhcpd_time() + CONFIG_NETUTILS_DHCPD_OFFERTIME; #endif /* Return the address in host order */ @@ -538,8 +541,9 @@ static inline bool dhcpd_parseoptions(void) * server inserts this option if the returned parameters will exceed the * usual space allotted for options. * - * If this option is present, the client interprets the specified additional - * fields after it concludes interpretation of the standard option fields. + * If this option is present, the client interprets the specified + * additional fields after it concludes interpretation of the standard + * option fields. * * Legal values for this option are: * @@ -619,6 +623,7 @@ static inline bool dhcpd_parseoptions(void) break; default: + /* Skip over unsupported options */ optlen = ptr[DHCPD_OPTION_LENGTH] + 2; @@ -807,7 +812,8 @@ static inline int dhcpd_socket(void) #ifdef HAVE_SO_REUSEADDR optval = 1; - ret = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (void*)&optval, sizeof(int)); + ret = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (FAR void *)&optval, + sizeof(int)); if (ret < 0) { nerr("ERROR: setsockopt SO_REUSEADDR failed: %d\n", errno); @@ -818,7 +824,8 @@ static inline int dhcpd_socket(void) #ifdef HAVE_SO_BROADCAST optval = 1; - ret = setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, (void*)&optval, sizeof(int)); + ret = setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, (FAR void *)&optval, + sizeof(int)); if (ret < 0) { nerr("ERROR: setsockopt SO_BROADCAST failed: %d\n", errno); @@ -828,7 +835,6 @@ static inline int dhcpd_socket(void) #endif return sockfd; - } /**************************************************************************** @@ -860,12 +866,12 @@ static inline int dhcpd_openresponder(void) ret = bind(sockfd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)); if (ret < 0) - { - nerr("ERROR: bind failed, port=%d addr=%08lx: %d\n", - addr.sin_port, (long)addr.sin_addr.s_addr, errno); - close(sockfd); - return ERROR; - } + { + nerr("ERROR: bind failed, port=%d addr=%08lx: %d\n", + addr.sin_port, (long)addr.sin_addr.s_addr, errno); + close(sockfd); + return ERROR; + } return sockfd; } @@ -897,6 +903,7 @@ static void dhcpd_initpacket(uint8_t mtype) { g_state.ds_outpacket.flags = 0; } + memset(g_state.ds_outpacket.giaddr, 0, 4); /* Add the generic options */ @@ -929,26 +936,34 @@ static int dhcpd_sendpacket(int bbroadcast) * with multicast; the value 0 to allows clients to request unicast. */ - ipaddr = INADDR_BROADCAST; + ipaddr = INADDR_BROADCAST; #else - /* Determine which address to respond to (or if we need to broadcast the response) + const uint8_t anyipaddr[4] = + { + }; + + /* Determine which address to respond to (or if we need to broadcast the + * response) * - * (1) If he caller know that it needs to multicast the response, it will set bbroadcast. - * (2) Otherwise, if the client already has and address (ciaddr), then use that for uni-cast - * (3) Broadcast if the client says it can't handle uni-cast (BOOTP_BROADCAST set) - * (4) Otherwise, the client claims it can handle the uni-casst response and we - * will uni-cast to the offered address (yiaddr). + * (1) If he caller know that it needs to multicast the response, it will + * set broadcast. + * (2) Otherwise, if the client already has and address (ciaddr), then use + * that for unicast + * (3) Broadcast if the client says it can't handle uni-cast (BOOTP_BROADCAST + * set) + * (4) Otherwise, the client claims it can handle the uni-casst response + * and we will uni-cast to the offered address (yiaddr). * - * NOTE: We really should also check the giaddr field. If no zero, the server should - * send any return messages to the 'DHCP server' port on the BOOTP relay agent whose - * address appears in 'giaddr'. + * NOTE: We really should also check the giaddr field. If no zero, the + * server should send any return messages to the 'DHCP server' port on the + * BOOTP relay agent whose address appears in 'giaddr'. */ if (bbroadcast) { ipaddr = INADDR_BROADCAST; } - else if (memcmp(g_state.ds_outpacket.ciaddr, g_anyipaddr, 4) != 0) + else if (memcmp(g_state.ds_outpacket.ciaddr, anyipaddr, 4) != 0) { dhcpd_arpupdate(g_state.ds_outpacket.ciaddr, g_state.ds_outpacket.chaddr); memcpy(&ipaddr, g_state.ds_outpacket.ciaddr, 4); @@ -980,7 +995,7 @@ static int dhcpd_sendpacket(int bbroadcast) /* Send the minimum sized packet that includes the END option */ - len = (g_state.ds_optend - (uint8_t*)&g_state.ds_outpacket) + 1; + len = (g_state.ds_optend - (FAR uint8_t *)&g_state.ds_outpacket) + 1; ninfo("sendto %08lx:%04x len=%d\n", (long)ntohl(addr.sin_addr.s_addr), ntohs(addr.sin_port), len); @@ -1026,7 +1041,7 @@ static inline int dhcpd_sendoffer(in_addr_t ipaddr, uint32_t leasetime) dhcpd_addoption32(DHCP_OPTION_ROUTER, htonl(CONFIG_NETUTILS_DHCPD_ROUTERIP)); #endif #ifdef HAVE_DSNIP - dhcp_addoption32p(DHCP_OPTION_DNS_SERVER, (FAR uint8_t*)&dnsaddr); + dhcp_addoption32p(DHCP_OPTION_DNS_SERVER, (FAR uint8_t *)&dnsaddr); #endif /* Send the offer response */ @@ -1088,7 +1103,7 @@ int dhcpd_sendack(in_addr_t ipaddr) dhcpd_addoption32(DHCP_OPTION_ROUTER, htonl(CONFIG_NETUTILS_DHCPD_ROUTERIP)); #endif #ifdef HAVE_DSNIP - dhcp_addoption32p(DHCP_OPTION_DNS_SERVER, (FAR uint8_t*)&dnsaddr); + dhcp_addoption32p(DHCP_OPTION_DNS_SERVER, (FAR uint8_t *)&dnsaddr); #endif #ifdef CONFIG_NETUTILS_DHCPD_IGNOREBROADCAST @@ -1131,6 +1146,7 @@ static inline int dhcpd_discover(void) } } #endif + /* Get the IP address associated with the lease (host order) */ ipaddr = dhcp_leaseipaddr(lease); @@ -1166,7 +1182,8 @@ static inline int dhcpd_discover(void) /* Reserve the leased IP for a shorter time for the offer */ - if (!dhcpd_setlease(g_state.ds_inpacket.chaddr, ipaddr, CONFIG_NETUTILS_DHCPD_OFFERTIME)) + if (!dhcpd_setlease(g_state.ds_inpacket.chaddr, ipaddr, + CONFIG_NETUTILS_DHCPD_OFFERTIME)) { nerr("ERROR: Failed to set lease\n"); return ERROR; @@ -1199,8 +1216,8 @@ static inline int dhcpd_request(void) lease = dhcpd_findbymac(g_state.ds_inpacket.chaddr); if (lease) { - /* Yes.. the client already holds a lease. Verify that the request is consistent - * with the existing lease (host order). + /* Yes.. the client already holds a lease. Verify that the request is + * consistent* with the existing lease (host order). */ ipaddr = dhcp_leaseipaddr(lease); @@ -1209,8 +1226,8 @@ static inline int dhcpd_request(void) if (g_state.ds_optserverip) { - /* ACK if the serverip is correct and the requested IP address is the one - * already offered to the client. + /* ACK if the serverip is correct and the requested IP address is + * the one already offered to the client. */ if (g_state.ds_optserverip == ntohl(g_state.ds_serverip) && @@ -1224,8 +1241,8 @@ static inline int dhcpd_request(void) } } - /* We have the lease and no server IP was requested. Was a specific IP address - * requested? (host order) + /* We have the lease and no server IP was requested. Was a specific IP + * address requested? (host order) */ else if (g_state.ds_optreqip) @@ -1287,10 +1304,21 @@ static inline int dhcpd_request(void) } } - /* No.. is the requested IP address in range? NAK if not */ + /* DHCPREQUEST without DHCPDISCOVER: + * The request IP address is in the range but has not been leased, + * maybe requested before the last shutdown, lease again. + */ - else if (g_state.ds_optreqip < CONFIG_NETUTILS_DHCPD_STARTIP || - g_state.ds_optreqip > CONFIG_NETUTILS_DHCP_OPTION_ENDIP) + else if (g_state.ds_optreqip >= CONFIG_NETUTILS_DHCPD_STARTIP && + g_state.ds_optreqip <= CONFIG_NETUTILS_DHCP_OPTION_ENDIP) + { + ipaddr = g_state.ds_optreqip; + response = DHCPACK; + } + + /* The requested IP address out of range, negative */ + + else { response = DHCPNAK; } @@ -1335,15 +1363,15 @@ static inline int dhcpd_decline(void) lease = dhcpd_findbymac(g_state.ds_inpacket.chaddr); if (lease) { - /* Disassociate the IP from the MAC, but prevent re-used of this - * address for a period of time. - */ + /* Disassociate the IP from the MAC, but prevent re-used of this + * address for a period of time. + */ - memset(lease->mac, 0, DHCP_HLEN_ETHERNET); + memset(lease->mac, 0, DHCP_HLEN_ETHERNET); #ifdef HAVE_LEASE_TIME - lease->expiry = dhcpd_time() + CONFIG_NETUTILS_DHCPD_DECLINETIME; + lease->expiry = dhcpd_time() + CONFIG_NETUTILS_DHCPD_DECLINETIME; #endif - } + } return OK; } @@ -1369,7 +1397,7 @@ static inline int dhcpd_release(void) * Name: dhcpd_openlistener ****************************************************************************/ -static inline int dhcpd_openlistener(void) +static inline int dhcpd_openlistener(FAR const char *interface) { struct sockaddr_in addr; struct ifreq req; @@ -1387,7 +1415,7 @@ static inline int dhcpd_openlistener(void) /* Get the IP address of the selected device */ - strncpy(req.ifr_name, CONFIG_NETUTILS_DHCPD_INTERFACE, IFNAMSIZ); + strncpy(req.ifr_name, interface, IFNAMSIZ); ret = ioctl(sockfd, SIOCGIFADDR, (unsigned long)&req); if (ret < 0) { @@ -1396,7 +1424,9 @@ static inline int dhcpd_openlistener(void) return ERROR; } - g_state.ds_serverip = ((struct sockaddr_in*)&req.ifr_addr)->sin_addr.s_addr; + g_state.ds_serverip = ((FAR struct sockaddr_in *) + &req.ifr_addr)->sin_addr.s_addr; + ninfo("serverip: %08lx\n", ntohl(g_state.ds_serverip)); /* Bind the socket to a local port. We have to bind to INADDRY_ANY to @@ -1427,7 +1457,7 @@ static inline int dhcpd_openlistener(void) * Name: dhcpd_run ****************************************************************************/ -int dhcpd_run(void) +int dhcpd_run(FAR const char *interface) { int sockfd; int nbytes; @@ -1441,13 +1471,13 @@ int dhcpd_run(void) /* Now loop indefinitely, reading packets from the DHCP server socket */ sockfd = -1; - for (;;) + for (; ; ) { /* Create a socket to listen for requests from DHCP clients */ if (sockfd < 0) { - sockfd = dhcpd_openlistener(); + sockfd = dhcpd_openlistener(interface); if (sockfd < 0) { nerr("ERROR: Failed to create socket\n"); @@ -1468,6 +1498,7 @@ int dhcpd_run(void) close(sockfd); sockfd = -1; } + continue; } @@ -1484,7 +1515,7 @@ int dhcpd_run(void) #ifdef CONFIG_NETUTILS_DHCPD_HOST /* Get the poor little uC a change to get its recvfrom in place */ - usleep(500*1000); + usleep(500 * 1000); #endif /* Now process the incoming DHCP message by its message type */ diff --git a/netutils/netinit/netinit.c b/netutils/netinit/netinit.c index d031ddb98..af35d3c47 100644 --- a/netutils/netinit/netinit.c +++ b/netutils/netinit/netinit.c @@ -439,29 +439,35 @@ static void netinit_net_bringup(void) handle = dhcpc_open(NET_DEVNAME, &mac, IFHWADDRLEN); - /* Get an IP address. Note that there is no logic for renewing the IP address in this - * example. The address should be renewed in ds.lease_time/2 seconds. + /* Get an IP address. Note that there is no logic for renewing the IP + * address in this example. The address should be renewed in + * ds.lease_time/2 seconds. */ if (handle != NULL) { - struct dhcpc_state ds; - dhcpc_request(handle, &ds); - netlib_set_ipv4addr(NET_DEVNAME, &ds.ipaddr); + struct dhcpc_state ds = + { + }; - if (ds.netmask.s_addr != 0) + if (dhcpc_request(handle, &ds) == OK) { - netlib_set_ipv4netmask(NET_DEVNAME, &ds.netmask); - } + netlib_set_ipv4addr(NET_DEVNAME, &ds.ipaddr); - if (ds.default_router.s_addr != 0) - { - netlib_set_dripv4addr(NET_DEVNAME, &ds.default_router); - } + if (ds.netmask.s_addr != 0) + { + netlib_set_ipv4netmask(NET_DEVNAME, &ds.netmask); + } - if (ds.dnsaddr.s_addr != 0) - { - netlib_set_ipv4dnsaddr(&ds.dnsaddr); + if (ds.default_router.s_addr != 0) + { + netlib_set_dripv4addr(NET_DEVNAME, &ds.default_router); + } + + if (ds.dnsaddr.s_addr != 0) + { + netlib_set_ipv4dnsaddr(&ds.dnsaddr); + } } dhcpc_close(handle);