123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832 |
- /*
- * File : dhcp_server_raw.c
- * A simple DHCP server implementation
- * COPYRIGHT (C) 2011-2023, Shanghai Real-Thread Technology Co., Ltd
- * http://www.rt-thread.com
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
- * OF SUCH DAMAGE.
- *
- * Change Logs:
- * Date Author Notes
- * 2014-04-01 Ren.Haibo the first version
- * 2018-06-12 aozima ignore DHCP_OPTION_SERVER_ID.
- */
- #include <stdio.h>
- #include <stdint.h>
- #include <rtthread.h>
- #include <lwip/opt.h>
- #include <lwip/sockets.h>
- #include <lwip/inet_chksum.h>
- #include <netif/etharp.h>
- #include <netif/ethernetif.h>
- #include <lwip/ip.h>
- #include <lwip/init.h>
- #if (LWIP_VERSION) < 0x02000000U
- #error "not support old LWIP"
- #endif
- #if !LWIP_IPV4
- #error "must enable IPV4"
- #endif
- #if (LWIP_VERSION) >= 0x02000000U
- #include <lwip/prot/dhcp.h>
- #endif
- /* DHCP server option */
- /* allocated client ip range */
- #ifndef DHCPD_CLIENT_IP_MIN
- #define DHCPD_CLIENT_IP_MIN 2
- #endif
- #ifndef DHCPD_CLIENT_IP_MAX
- #define DHCPD_CLIENT_IP_MAX 254
- #endif
- /* the DHCP server address */
- #ifndef DHCPD_SERVER_IP
- #define DHCPD_SERVER_IP "192.168.169.1"
- #endif
- #define DHCP_DEBUG_PRINTF
- #ifdef DHCP_DEBUG_PRINTF
- #define DEBUG_PRINTF rt_kprintf("[DHCP] "); rt_kprintf
- #else
- #define DEBUG_PRINTF(...)
- #endif /* DHCP_DEBUG_PRINTF */
- /* we need some routines in the DHCP of lwIP */
- #undef LWIP_DHCP
- #define LWIP_DHCP 1
- #include <lwip/dhcp.h>
- /** Mac address length */
- #define DHCP_MAX_HLEN 6
- /** dhcp default live time */
- #define DHCP_DEFAULT_LIVE_TIME 0x80510100
- /** Minimum length for request before packet is parsed */
- #define DHCP_MIN_REQUEST_LEN 44
- #define LWIP_NETIF_LOCK(...)
- #define LWIP_NETIF_UNLOCK(...)
- #ifndef DHCP_SERVER_PORT
- #define DHCP_SERVER_PORT 67
- #endif
- /**
- * The dhcp client node struct.
- */
- struct dhcp_client_node
- {
- struct dhcp_client_node *next;
- u8_t chaddr[DHCP_MAX_HLEN];
- ip4_addr_t ipaddr;
- u32_t lease_end;
- };
- /**
- * The dhcp server struct.
- */
- struct dhcp_server
- {
- struct dhcp_server *next;
- struct netif *netif;
- struct udp_pcb *pcb;
- struct dhcp_client_node *node_list;
- ip4_addr_t start;
- ip4_addr_t end;
- ip4_addr_t current;
- };
- static u8_t *dhcp_server_option_find(u8_t *buf, u16_t len, u8_t option);
- /**
- * The dhcp server struct list.
- */
- static struct dhcp_server *lw_dhcp_server;
- /**
- * Find a dhcp client node by mac address
- *
- * @param dhcpserver The dhcp server
- * @param chaddr Mac address
- * @param hlen Mac address length
- * @return dhcp client node
- */
- static struct dhcp_client_node *
- dhcp_client_find_by_mac(struct dhcp_server *dhcpserver, const u8_t *chaddr, u8_t hlen)
- {
- struct dhcp_client_node *node;
- for (node = dhcpserver->node_list; node != NULL; node = node->next)
- {
- if (memcmp(node->chaddr, chaddr, hlen) == 0)
- {
- return node;
- }
- }
- return NULL;
- }
- /**
- * Find a dhcp client node by ip address
- *
- * @param dhcpserver The dhcp server
- * @param ip IP address
- * @return dhcp client node
- */
- static struct dhcp_client_node *
- dhcp_client_find_by_ip(struct dhcp_server *dhcpserver, const ip4_addr_t *ip)
- {
- struct dhcp_client_node *node;
- for (node = dhcpserver->node_list; node != NULL; node = node->next)
- {
- if (ip4_addr_cmp(&node->ipaddr, ip))
- {
- return node;
- }
- }
- return NULL;
- }
- /**
- * Find a dhcp client node by dhcp message
- *
- * @param dhcpserver is the dhcp server
- * @param msg is the dhcp message
- * @param opt_buf is the optional buffer
- * @param len is the buffer length
- * @return dhcp client node
- */
- static struct dhcp_client_node *
- dhcp_client_find(struct dhcp_server *dhcpserver, struct dhcp_msg *msg,
- u8_t *opt_buf, u16_t len)
- {
- u8_t *opt;
- //u32_t ipaddr;
- struct dhcp_client_node *node;
- node = dhcp_client_find_by_mac(dhcpserver, msg->chaddr, msg->hlen);
- if (node != NULL)
- {
- return node;
- }
- opt = dhcp_server_option_find(opt_buf, len, DHCP_OPTION_REQUESTED_IP);
- if (opt != NULL)
- {
- node = dhcp_client_find_by_ip(dhcpserver, (ip4_addr_t *)(&opt[2]));
- if (node != NULL)
- {
- return node;
- }
- }
- return NULL;
- }
- /**
- * Allocate a dhcp client node by dhcp message
- *
- * @param dhcpserver is the dhcp server
- * @param msg is the dhcp message
- * @param opt_buf is the optional buffer
- * @param len is the buffer length
- * @return dhcp client node
- */
- static struct dhcp_client_node *
- dhcp_client_alloc(struct dhcp_server *dhcpserver, struct dhcp_msg *msg,
- u8_t *opt_buf, u16_t len)
- {
- u8_t *opt;
- u32_t ipaddr;
- struct dhcp_client_node *node;
- node = dhcp_client_find_by_mac(dhcpserver, msg->chaddr, msg->hlen);
- if (node != NULL)
- {
- return node;
- }
- opt = dhcp_server_option_find(opt_buf, len, DHCP_OPTION_REQUESTED_IP);
- if (opt != NULL)
- {
- node = dhcp_client_find_by_ip(dhcpserver, (ip4_addr_t *)(&opt[2]));
- if (node != NULL)
- {
- return node;
- }
- }
- dhcp_alloc_again:
- node = dhcp_client_find_by_ip(dhcpserver, &dhcpserver->current);
- if (node != NULL)
- {
- ipaddr = (ntohl(dhcpserver->current.addr) + 1);
- if (ipaddr > ntohl(dhcpserver->end.addr))
- {
- ipaddr = ntohl(dhcpserver->start.addr);
- }
- dhcpserver->current.addr = htonl(ipaddr);
- goto dhcp_alloc_again;
- }
- node = (struct dhcp_client_node *)mem_malloc(sizeof(struct dhcp_client_node));
- if (node == NULL)
- {
- return NULL;
- }
- SMEMCPY(node->chaddr, msg->chaddr, msg->hlen);
- node->ipaddr = dhcpserver->current;
- node->next = dhcpserver->node_list;
- dhcpserver->node_list = node;
- return node;
- }
- /**
- * find option from buffer.
- *
- * @param buf The buffer to find option
- * @param len The buffer length
- * @param option Which option to find
- * @return dhcp option buffer
- */
- static u8_t *
- dhcp_server_option_find(u8_t *buf, u16_t len, u8_t option)
- {
- u8_t *end = buf + len;
- while ((buf < end) && (*buf != DHCP_OPTION_END))
- {
- if (*buf == option)
- {
- return buf;
- }
- buf += (buf[1] + 2);
- }
- return NULL;
- }
- /**
- * If an incoming DHCP message is in response to us, then trigger the state machine
- */
- static void
- dhcp_server_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *recv_addr, u16_t port)
- {
- struct dhcp_server *dhcp_server = (struct dhcp_server *)arg;
- struct dhcp_msg *msg;
- struct pbuf *q;
- u8_t *opt_buf;
- u8_t *opt;
- struct dhcp_client_node *node;
- u8_t msg_type;
- u16_t length;
- ip_addr_t addr = *recv_addr;
- u32_t tmp;
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("[%s:%d] %c%c recv %d\n", __FUNCTION__, __LINE__, dhcp_server->netif->name[0], dhcp_server->netif->name[1], p->tot_len));
- /* prevent warnings about unused arguments */
- LWIP_UNUSED_ARG(pcb);
- LWIP_UNUSED_ARG(addr);
- LWIP_UNUSED_ARG(port);
- if (p->len < DHCP_MIN_REQUEST_LEN)
- {
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("DHCP request message or pbuf too short\n"));
- pbuf_free(p);
- return;
- }
- q = pbuf_alloc(PBUF_TRANSPORT, 1500, PBUF_RAM);
- if (q == NULL)
- {
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("pbuf_alloc dhcp_msg failed!\n"));
- pbuf_free(p);
- return;
- }
- if (q->tot_len < p->tot_len)
- {
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("pbuf_alloc dhcp_msg too small %d:%d\n", q->tot_len, p->tot_len));
- pbuf_free(p);
- return;
- }
- pbuf_copy(q, p);
- pbuf_free(p);
- msg = (struct dhcp_msg *)q->payload;
- if (msg->op != DHCP_BOOTREQUEST)
- {
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("not a DHCP request message, but type %"U16_F"\n", (u16_t)msg->op));
- goto free_pbuf_and_return;
- }
- if (msg->cookie != PP_HTONL(DHCP_MAGIC_COOKIE))
- {
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("bad DHCP_MAGIC_COOKIE!\n"));
- goto free_pbuf_and_return;
- }
- if (msg->hlen > DHCP_MAX_HLEN)
- {
- goto free_pbuf_and_return;
- }
- opt_buf = (u8_t *)msg + DHCP_OPTIONS_OFS;
- length = q->tot_len - DHCP_OPTIONS_OFS;
- opt = dhcp_server_option_find(opt_buf, length, DHCP_OPTION_MESSAGE_TYPE);
- if (opt)
- {
- msg_type = *(opt + 2);
- if (msg_type == DHCP_DISCOVER)
- {
- node = dhcp_client_alloc(dhcp_server, msg, opt_buf, length);
- if (node == NULL)
- {
- goto free_pbuf_and_return;
- }
- node->lease_end = DHCP_DEFAULT_LIVE_TIME;
- /* create dhcp offer and send */
- msg->op = DHCP_BOOTREPLY;
- msg->hops = 0;
- msg->secs = 0;
- SMEMCPY(&msg->siaddr, &(dhcp_server->netif->ip_addr), 4);
- msg->sname[0] = '\0';
- msg->file[0] = '\0';
- msg->cookie = PP_HTONL(DHCP_MAGIC_COOKIE);
- SMEMCPY(&msg->yiaddr, &node->ipaddr, 4);
- opt_buf = (u8_t *)msg + DHCP_OPTIONS_OFS;
- /* add msg type */
- *opt_buf++ = DHCP_OPTION_MESSAGE_TYPE;
- *opt_buf++ = 1;
- *opt_buf++ = DHCP_OFFER;
- /* add server id */
- *opt_buf++ = DHCP_OPTION_SERVER_ID;
- *opt_buf++ = 4;
- SMEMCPY(opt_buf, &(dhcp_server->netif->ip_addr), 4);
- opt_buf += 4;
- /* add_lease_time */
- *opt_buf++ = DHCP_OPTION_LEASE_TIME;
- *opt_buf++ = 4;
- tmp = PP_HTONL(DHCP_DEFAULT_LIVE_TIME);
- SMEMCPY(opt_buf, &tmp, 4);
- opt_buf += 4;
- /* add config */
- *opt_buf++ = DHCP_OPTION_SUBNET_MASK;
- *opt_buf++ = 4;
- SMEMCPY(opt_buf, &ip_2_ip4(&dhcp_server->netif->netmask)->addr, 4);
- opt_buf += 4;
- *opt_buf++ = DHCP_OPTION_DNS_SERVER;
- *opt_buf++ = 4;
- #ifdef DHCP_DNS_SERVER_IP
- {
- ip_addr_t dns_addr;
- ipaddr_aton(DHCP_DNS_SERVER_IP, &dns_addr);
- SMEMCPY(opt_buf, &ip_2_ip4(&dns_addr)->addr, 4);
- }
- #else
- /* default use gatewary dns server */
- SMEMCPY(opt_buf, &(dhcp_server->netif->ip_addr), 4);
- #endif /* DHCP_DNS_SERVER_IP */
- opt_buf += 4;
- *opt_buf++ = DHCP_OPTION_ROUTER;
- *opt_buf++ = 4;
- SMEMCPY(opt_buf, &ip_2_ip4(&dhcp_server->netif->ip_addr)->addr, 4);
- opt_buf += 4;
- /* add option end */
- *opt_buf++ = DHCP_OPTION_END;
- length = (u32_t)opt_buf - (u32_t)msg;
- if (length < q->tot_len)
- {
- pbuf_realloc(q, length);
- }
- ip_2_ip4(&addr)->addr = INADDR_BROADCAST;
- udp_sendto_if(pcb, q, &addr, port, dhcp_server->netif);
- }
- else
- {
- if (1)
- {
- if (msg_type == DHCP_REQUEST)
- {
- node = dhcp_client_find(dhcp_server, msg, opt_buf, length);
- if (node != NULL)
- {
- /* Send ack */
- node->lease_end = DHCP_DEFAULT_LIVE_TIME;
- /* create dhcp offer and send */
- msg->op = DHCP_BOOTREPLY;
- msg->hops = 0;
- msg->secs = 0;
- SMEMCPY(&msg->siaddr, &(dhcp_server->netif->ip_addr), 4);
- msg->sname[0] = '\0';
- msg->file[0] = '\0';
- msg->cookie = PP_HTONL(DHCP_MAGIC_COOKIE);
- SMEMCPY(&msg->yiaddr, &node->ipaddr, 4);
- opt_buf = (u8_t *)msg + DHCP_OPTIONS_OFS;
- /* add msg type */
- *opt_buf++ = DHCP_OPTION_MESSAGE_TYPE;
- *opt_buf++ = 1;
- *opt_buf++ = DHCP_ACK;
- /* add server id */
- *opt_buf++ = DHCP_OPTION_SERVER_ID;
- *opt_buf++ = 4;
- SMEMCPY(opt_buf, &(dhcp_server->netif->ip_addr), 4);
- opt_buf += 4;
- /* add_lease_time */
- *opt_buf++ = DHCP_OPTION_LEASE_TIME;
- *opt_buf++ = 4;
- tmp = PP_HTONL(DHCP_DEFAULT_LIVE_TIME);
- SMEMCPY(opt_buf, &tmp, 4);
- opt_buf += 4;
- /* add config */
- *opt_buf++ = DHCP_OPTION_SUBNET_MASK;
- *opt_buf++ = 4;
- SMEMCPY(opt_buf, &ip_2_ip4(&dhcp_server->netif->netmask)->addr, 4);
- opt_buf += 4;
- *opt_buf++ = DHCP_OPTION_DNS_SERVER;
- *opt_buf++ = 4;
- #ifdef DHCP_DNS_SERVER_IP
- {
- ip_addr_t dns_addr;
- ipaddr_aton(DHCP_DNS_SERVER_IP, &dns_addr);
- SMEMCPY(opt_buf, &ip_2_ip4(&dns_addr)->addr, 4);
- }
- #else
- /* default use gatewary dns server */
- SMEMCPY(opt_buf, &(dhcp_server->netif->ip_addr), 4);
- #endif /* DHCP_DNS_SERVER_IP */
- opt_buf += 4;
- *opt_buf++ = DHCP_OPTION_ROUTER;
- *opt_buf++ = 4;
- SMEMCPY(opt_buf, &ip_2_ip4(&dhcp_server->netif->ip_addr)->addr, 4);
- opt_buf += 4;
- /* add option end */
- *opt_buf++ = DHCP_OPTION_END;
- length = (u32_t)opt_buf - (u32_t)msg;
- if (length < q->tot_len)
- {
- pbuf_realloc(q, length);
- }
- ip_2_ip4(&addr)->addr = INADDR_BROADCAST;
- udp_sendto_if(pcb, q, &addr, port, dhcp_server->netif);
- }
- else
- {
- /* Send no ack */
- /* create dhcp offer and send */
- msg->op = DHCP_BOOTREPLY;
- msg->hops = 0;
- msg->secs = 0;
- SMEMCPY(&msg->siaddr, &(dhcp_server->netif->ip_addr), 4);
- msg->sname[0] = '\0';
- msg->file[0] = '\0';
- msg->cookie = PP_HTONL(DHCP_MAGIC_COOKIE);
- memset(&msg->yiaddr, 0, 4);
- opt_buf = (u8_t *)msg + DHCP_OPTIONS_OFS;
- /* add msg type */
- *opt_buf++ = DHCP_OPTION_MESSAGE_TYPE;
- *opt_buf++ = 1;
- *opt_buf++ = DHCP_NAK;
- /* add server id */
- *opt_buf++ = DHCP_OPTION_SERVER_ID;
- *opt_buf++ = 4;
- SMEMCPY(opt_buf, &(dhcp_server->netif->ip_addr), 4);
- opt_buf += 4;
- /* add option end */
- *opt_buf++ = DHCP_OPTION_END;
- length = (u32_t)opt_buf - (u32_t)msg;
- if (length < q->tot_len)
- {
- pbuf_realloc(q, length);
- }
- ip_2_ip4(&addr)->addr = INADDR_BROADCAST;
- udp_sendto_if(pcb, q, &addr, port, dhcp_server->netif);
- }
- }
- else if (msg_type == DHCP_RELEASE)
- {
- struct dhcp_client_node *node_prev = NULL;
- for (node = dhcp_server->node_list; node != NULL; node = node->next)
- {
- if (memcmp(node->chaddr, msg->chaddr, msg->hlen) == 0)
- {
- if (node == dhcp_server->node_list)
- {
- dhcp_server->node_list = node->next;
- }
- else
- {
- node_prev->next = node->next;
- }
- break;
- }
- node_prev = node;
- node = node->next;
- }
- if (node != NULL)
- {
- mem_free(node);
- }
- }
- else if (msg_type == DHCP_DECLINE)
- {
- ;
- }
- else if (msg_type == DHCP_INFORM)
- {
- ;
- }
- }
- }
- }
- free_pbuf_and_return:
- pbuf_free(q);
- }
- /**
- * start dhcp server for a netif
- *
- * @param netif The netif which use dhcp server
- * @param start The Start IP address
- * @param end The End IP address
- * @return lwIP error code
- * - ERR_OK - No error
- * - ERR_MEM - Out of memory
- */
- err_t
- dhcp_server_start(struct netif *netif, ip4_addr_t *start, ip4_addr_t *end)
- {
- struct dhcp_server *dhcp_server;
- /* If this netif alreday use the dhcp server. */
- for (dhcp_server = lw_dhcp_server; dhcp_server != NULL; dhcp_server = dhcp_server->next)
- {
- if (dhcp_server->netif == netif)
- {
- dhcp_server->start = *start;
- dhcp_server->end = *end;
- dhcp_server->current = *start;
- return ERR_OK;
- }
- }
- dhcp_server = NULL;
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_server_start(): starting new DHCP server\n"));
- dhcp_server = (struct dhcp_server *)mem_malloc(sizeof(struct dhcp_server));
- if (dhcp_server == NULL)
- {
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_server_start(): could not allocate dhcp\n"));
- return ERR_MEM;
- }
- /* clear data structure */
- memset(dhcp_server, 0, sizeof(struct dhcp_server));
- /* store this dhcp server to list */
- dhcp_server->next = lw_dhcp_server;
- lw_dhcp_server = dhcp_server;
- dhcp_server->netif = netif;
- dhcp_server->node_list = NULL;
- dhcp_server->start = *start;
- dhcp_server->end = *end;
- dhcp_server->current = *start;
- /* allocate UDP PCB */
- dhcp_server->pcb = udp_new();
- if (dhcp_server->pcb == NULL)
- {
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_server_start(): could not obtain pcb\n"));
- return ERR_MEM;
- }
- ip_set_option(dhcp_server->pcb, SOF_BROADCAST);
- /* set up local and remote port for the pcb */
- udp_bind(dhcp_server->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);
- //udp_connect(dhcp_server->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
- /* set up the recv callback and argument */
- udp_recv(dhcp_server->pcb, dhcp_server_recv, dhcp_server);
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_server_start(): starting DHCP server\n"));
- return ERR_OK;
- }
- extern void set_if(const char *netif_name, const char *ip_addr, const char *gw_addr, const char *nm_addr);
- void dhcpd_start(const char *netif_name)
- {
- struct netif *netif = netif_list;
- err_t res;
- DEBUG_PRINTF("%s: %s\r\n", __FUNCTION__, netif_name);
- LWIP_NETIF_LOCK();
- if (strlen(netif_name) > sizeof(netif->name))
- {
- DEBUG_PRINTF("network interface name too long!\r\n");
- goto _exit;
- }
- while (netif != RT_NULL)
- {
- if (strncmp(netif_name, netif->name, sizeof(netif->name)) == 0)
- break;
- netif = netif->next;
- if (netif == RT_NULL)
- {
- DEBUG_PRINTF("network interface: %s not found!\r\n", netif_name);
- break;
- }
- }
- if (netif == RT_NULL)
- {
- goto _exit;
- }
- if (1)
- {
- dhcp_stop(netif);
- set_if(netif_name, DHCPD_SERVER_IP, "0.0.0.0", "255.255.255.0");
- netif_set_up(netif);
- }
- {
- char str_tmp[4 * 4 + 4] = DHCPD_SERVER_IP;
- char *p = str_tmp;
- ip4_addr_t ip_start, ip_end;
- p = strchr(str_tmp, '.');
- if (p)
- {
- p = strchr(p + 1, '.');
- if (p)
- {
- p = strchr(p + 1, '.');
- }
- }
- if (!p)
- {
- DEBUG_PRINTF("DHCPD_SERVER_IP: %s error!\r\n", str_tmp);
- goto _exit;
- }
- p = p + 1; /* move to xxx.xxx.xxx.^ */
- sprintf(p, "%d", DHCPD_CLIENT_IP_MIN);
- ip4addr_aton(str_tmp, &ip_start);
- DEBUG_PRINTF("ip_start: [%s]\r\n", str_tmp);
- sprintf(p, "%d", DHCPD_CLIENT_IP_MAX);
- ip4addr_aton(str_tmp, &ip_end);
- DEBUG_PRINTF("ip_end: [%s]\r\n", str_tmp);
- res = dhcp_server_start(netif, &ip_start, &ip_end);
- if (res != 0)
- {
- DEBUG_PRINTF("dhcp_server_start res: %s.\r\n", res);
- }
- }
- _exit:
- LWIP_NETIF_UNLOCK();
- return;
- }
- void dhcpd_stop(const char *netif_name)
- {
- struct dhcp_server *dhcp_server, *server_node;
- struct netif *netif = netif_list;
- struct dhcp_client_node *node, *next;
- DEBUG_PRINTF("%s: %s\r\n", __FUNCTION__, netif_name);
- LWIP_NETIF_LOCK();
- if (strlen(netif_name) > sizeof(netif->name))
- {
- DEBUG_PRINTF("network interface name too long!\r\n");
- goto _exit;
- }
- while (netif != RT_NULL)
- {
- if (strncmp(netif_name, netif->name, sizeof(netif->name)) == 0)
- break;
- netif = netif->next;
- if (netif == RT_NULL)
- {
- DEBUG_PRINTF("network interface: %s not found!\r\n", netif_name);
- break;
- }
- }
- if (netif == RT_NULL)
- {
- goto _exit;
- }
- /* If this netif alreday use the dhcp server. */
- for (dhcp_server = lw_dhcp_server; dhcp_server != NULL; dhcp_server = dhcp_server->next)
- {
- if (dhcp_server->netif == netif)
- {
- break;
- }
- }
- if (dhcp_server == RT_NULL)
- {
- goto _exit;
- }
- /* remove dhcp server */
- if (dhcp_server == lw_dhcp_server)
- {
- lw_dhcp_server = lw_dhcp_server->next;
- }
- else
- {
- server_node = lw_dhcp_server;
- while (server_node->next && server_node->next != dhcp_server)
- {
- server_node = server_node->next;
- }
- if (server_node->next != RT_NULL)
- {
- server_node->next = server_node->next->next;
- }
- }
- udp_disconnect(dhcp_server->pcb);
- udp_remove(dhcp_server->pcb);
- /* remove all client node */
- for (node = dhcp_server->node_list; node != NULL; node = next)
- {
- next = node->next;
- mem_free(node);
- }
- mem_free(dhcp_server);
- set_if(netif_name, "0.0.0.0", "0.0.0.0", "0.0.0.0");
- _exit:
- LWIP_NETIF_UNLOCK();
- }
|