diff --git a/components/net/lwip_dhcpd/dhcp_server.c b/components/net/lwip_dhcpd/dhcp_server.c index 13c6ecc7e1..d2e644cb93 100644 --- a/components/net/lwip_dhcpd/dhcp_server.c +++ b/components/net/lwip_dhcpd/dhcp_server.c @@ -25,6 +25,7 @@ * 2013-01-30 aozima the first version * 2013-08-08 aozima support different network segments. * 2015-01-30 bernard release to RT-Thread RTOS. + * 2017-12-27 aozima add [mac-ip] table support. */ #include @@ -77,7 +78,25 @@ /* buffer size for receive DHCP packet */ #define BUFSZ 1024 -static uint8_t next_client_ip = DHCPD_CLIENT_IP_MIN; +#ifndef MAC_ADDR_LEN +#define MAC_ADDR_LEN 6 +#endif + +#ifndef MAC_TABLE_LEN +#define MAC_TABLE_LEN 4 +#endif + +struct mac_addr_t +{ + uint8_t add[MAC_ADDR_LEN]; +}; + +struct mac_ip_item_t +{ + struct mac_addr_t mac_addr; + uint8_t ip_addr_3; +}; + static rt_err_t _low_level_dhcp_send(struct netif *netif, const void *buffer, rt_size_t size) @@ -128,6 +147,63 @@ static rt_err_t _low_level_dhcp_send(struct netif *netif, return RT_EOK; } +static uint8_t get_ip(struct mac_addr_t *p_mac_addr) +{ + static uint8_t next_client_ip = DHCPD_CLIENT_IP_MIN; + static struct mac_ip_item_t mac_table[MAC_TABLE_LEN]; + static int offset = 0; + + struct mac_addr_t bad_mac; + int i; + uint8_t ip_addr_3; + + rt_memset(&bad_mac, 0, sizeof(bad_mac)); + if (!rt_memcmp(&bad_mac, p_mac_addr, sizeof(bad_mac))) + { + DEBUG_PRINTF("mac address all zero"); + ip_addr_3 = DHCPD_CLIENT_IP_MAX; + goto _return; + } + + rt_memset(&bad_mac, 0xFF, sizeof(bad_mac)); + if (!rt_memcmp(&bad_mac, p_mac_addr, sizeof(bad_mac))) + { + DEBUG_PRINTF("mac address all one"); + ip_addr_3 = DHCPD_CLIENT_IP_MAX; + goto _return; + } + + for (i = 0; i < MAC_TABLE_LEN; i++) + { + if (!rt_memcmp(&mac_table[i].mac_addr, p_mac_addr, sizeof(bad_mac))) + { + //use old ip + ip_addr_3 = mac_table[i].ip_addr_3; + DEBUG_PRINTF("return old ip: %d\n", (int)ip_addr_3); + goto _return; + } + } + + /* add new ip */ + mac_table[offset].mac_addr = *p_mac_addr; + mac_table[offset].ip_addr_3 = next_client_ip; + ip_addr_3 = mac_table[offset].ip_addr_3 ; + + offset++; + if (offset >= MAC_TABLE_LEN) + offset = 0; + + next_client_ip++; + if (next_client_ip > DHCPD_CLIENT_IP_MAX) + next_client_ip = DHCPD_CLIENT_IP_MIN; + + DEBUG_PRINTF("create new ip: %d\n", (int)ip_addr_3); + DEBUG_PRINTF("next_client_ip %d\n", next_client_ip); + +_return: + return ip_addr_3; +} + static void dhcpd_thread_entry(void *parameter) { struct netif *netif = RT_NULL; @@ -138,6 +214,7 @@ static void dhcpd_thread_entry(void *parameter) struct sockaddr_in server_addr, client_addr; struct dhcp_msg *msg; int optval = 1; + struct mac_addr_t mac_addr; /* get ethernet interface. */ netif = (struct netif *) parameter; @@ -206,6 +283,8 @@ static void dhcpd_thread_entry(void *parameter) continue; } + memcpy(mac_addr.add, msg->chaddr, MAC_ADDR_LEN); + /* handler. */ { uint8_t *dhcp_opt; @@ -216,6 +295,10 @@ static void dhcpd_thread_entry(void *parameter) uint8_t finished = 0; uint32_t request_ip = 0; + uint8_t client_ip_3; + + client_ip_3 = get_ip(&mac_addr); + dhcp_opt = (uint8_t *)msg + DHCP_OPTIONS_OFS; while (finished == 0) { @@ -251,7 +334,9 @@ static void dhcpd_thread_entry(void *parameter) if (request_ip) { uint32_t client_ip = DHCPD_SERVER_IPADDR0 << 24 | DHCPD_SERVER_IPADDR1 << 16 - | DHCPD_SERVER_IPADDR2 << 8 | (next_client_ip); + | DHCPD_SERVER_IPADDR2 << 8 | client_ip_3; + + DEBUG_PRINTF("message_type: %d, request_ip: %08X, client_ip: %08X.\n", message_type, request_ip, client_ip); if (request_ip != client_ip) { @@ -261,15 +346,14 @@ static void dhcpd_thread_entry(void *parameter) *dhcp_opt++ = DHCP_OPTION_END; DEBUG_PRINTF("requested IP invalid, reply DHCP_NAK\n"); + if (netif != RT_NULL) { int send_byte = (dhcp_opt - (uint8_t *)msg); _low_level_dhcp_send(netif, msg, send_byte); DEBUG_PRINTF("DHCP server send %d byte\n", send_byte); } - next_client_ip++; - if (next_client_ip > DHCPD_CLIENT_IP_MAX) - next_client_ip = DHCPD_CLIENT_IP_MIN; + continue; } } @@ -366,7 +450,7 @@ static void dhcpd_thread_entry(void *parameter) msg->op = DHCP_BOOTREPLY; IP4_ADDR(&msg->yiaddr, DHCPD_SERVER_IPADDR0, DHCPD_SERVER_IPADDR1, - DHCPD_SERVER_IPADDR2, next_client_ip); + DHCPD_SERVER_IPADDR2, client_ip_3); client_addr.sin_addr.s_addr = INADDR_BROADCAST; @@ -381,7 +465,7 @@ static void dhcpd_thread_entry(void *parameter) } } -void dhcpd_start(char *netif_name) +void dhcpd_start(const char *netif_name) { rt_thread_t thread; struct netif *netif = netif_list; @@ -406,7 +490,7 @@ void dhcpd_start(char *netif_name) if (1) { - extern void set_if(char *netif_name, char *ip_addr, char *gw_addr, char *nm_addr); + extern void set_if(const char *netif_name, const char *ip_addr, const char *gw_addr, const char *nm_addr); char ip_str[4 * 4 + 1]; diff --git a/components/net/lwip_dhcpd/dhcp_server.h b/components/net/lwip_dhcpd/dhcp_server.h index 4bd1163706..981337e6b1 100644 --- a/components/net/lwip_dhcpd/dhcp_server.h +++ b/components/net/lwip_dhcpd/dhcp_server.h @@ -25,12 +25,13 @@ * 2013-01-30 aozima the first version * 2013-08-08 aozima support different network segments. * 2015-01-30 bernard release to RT-Thread RTOS. + * 2017-12-27 aozima add [mac-ip] table support. */ #ifndef DHCPV4_SERVER_H__ #define DHCPV4_SERVER_H__ -void dhcpd_start(char* netif_name); +void dhcpd_start(const char* netif_name); #endif