dhcpserver.c 41 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433
  1. /*
  2. * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. //#include "esp_common.h"
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include "lwip/dhcp.h"
  10. #include "lwip/err.h"
  11. #include "lwip/pbuf.h"
  12. #include "lwip/udp.h"
  13. #include "lwip/mem.h"
  14. #include "lwip/ip_addr.h"
  15. #include "lwip/timeouts.h"
  16. #include "dhcpserver/dhcpserver.h"
  17. #include "dhcpserver/dhcpserver_options.h"
  18. #if ESP_DHCPS
  19. #ifdef LWIP_HOOK_FILENAME
  20. #include LWIP_HOOK_FILENAME
  21. #endif
  22. #ifndef LWIP_HOOK_DHCPS_POST_APPEND_OPTS
  23. #define LWIP_HOOK_DHCPS_POST_APPEND_OPTS(netif, dhcps, state, pp_opts)
  24. #endif
  25. #define BOOTP_BROADCAST 0x8000
  26. #define DHCP_REQUEST 1
  27. #define DHCP_REPLY 2
  28. #define DHCP_HTYPE_ETHERNET 1
  29. #define DHCP_HLEN_ETHERNET 6
  30. #define DHCP_MSG_LEN 236
  31. #define DHCPS_SERVER_PORT 67
  32. #define DHCPS_CLIENT_PORT 68
  33. #define DHCPDISCOVER 1
  34. #define DHCPOFFER 2
  35. #define DHCPREQUEST 3
  36. #define DHCPDECLINE 4
  37. #define DHCPACK 5
  38. #define DHCPNAK 6
  39. #define DHCPRELEASE 7
  40. #define DHCP_OPTION_SUBNET_MASK 1
  41. #define DHCP_OPTION_ROUTER 3
  42. #define DHCP_OPTION_DNS_SERVER 6
  43. #define DHCP_OPTION_REQ_IPADDR 50
  44. #define DHCP_OPTION_LEASE_TIME 51
  45. #define DHCP_OPTION_MSG_TYPE 53
  46. #define DHCP_OPTION_SERVER_ID 54
  47. #define DHCP_OPTION_INTERFACE_MTU 26
  48. #define DHCP_OPTION_PERFORM_ROUTER_DISCOVERY 31
  49. #define DHCP_OPTION_BROADCAST_ADDRESS 28
  50. #define DHCP_OPTION_REQ_LIST 55
  51. #define DHCP_OPTION_END 255
  52. //#define USE_CLASS_B_NET 1
  53. #define DHCPS_DEBUG 0
  54. #define DHCPS_LOG printf
  55. #define MAX_STATION_NUM CONFIG_LWIP_DHCPS_MAX_STATION_NUM
  56. #define DHCPS_STATE_OFFER 1
  57. #define DHCPS_STATE_DECLINE 2
  58. #define DHCPS_STATE_ACK 3
  59. #define DHCPS_STATE_NAK 4
  60. #define DHCPS_STATE_IDLE 5
  61. #define DHCPS_STATE_RELEASE 6
  62. typedef enum {
  63. DHCPS_HANDLE_CREATED = 0,
  64. DHCPS_HANDLE_STARTED,
  65. DHCPS_HANDLE_STOPPED,
  66. DHCPS_HANDLE_DELETE_PENDING,
  67. } dhcps_handle_state;
  68. typedef struct list_node {
  69. void *pnode;
  70. struct list_node *pnext;
  71. } list_node;
  72. typedef struct {
  73. ip4_addr_t ip;
  74. ip4_addr_t netmask;
  75. ip4_addr_t gw;
  76. } ip_info_t;
  77. ////////////////////////////////////////////////////////////////////////////////////
  78. static const u32_t magic_cookie = 0x63538263;
  79. struct dhcps_t {
  80. struct netif *dhcps_netif;
  81. ip4_addr_t broadcast_dhcps;
  82. ip4_addr_t server_address;
  83. ip4_addr_t dns_server;
  84. ip4_addr_t client_address;
  85. ip4_addr_t client_address_plus;
  86. ip4_addr_t dhcps_mask;
  87. list_node *plist;
  88. bool renew;
  89. dhcps_lease_t dhcps_poll;
  90. dhcps_time_t dhcps_lease_time;
  91. dhcps_offer_t dhcps_offer;
  92. dhcps_offer_t dhcps_dns;
  93. dhcps_cb_t dhcps_cb;
  94. void* dhcps_cb_arg;
  95. struct udp_pcb *dhcps_pcb;
  96. dhcps_handle_state state;
  97. };
  98. static void dhcps_tmr(void* arg);
  99. dhcps_t *dhcps_new(void)
  100. {
  101. dhcps_t *dhcps = mem_calloc(1, sizeof(dhcps_t));
  102. if (dhcps == NULL) {
  103. return NULL;
  104. }
  105. dhcps->dhcps_netif = NULL;
  106. dhcps->dns_server.addr = 0;
  107. #ifdef USE_CLASS_B_NET
  108. dhcps->dhcps_mask.addr = PP_HTONL(LWIP_MAKEU32(255, 240, 0, 0));
  109. #else
  110. dhcps->dhcps_mask.addr = PP_HTONL(LWIP_MAKEU32(255, 255, 255, 0));
  111. #endif
  112. dhcps->plist = NULL;
  113. dhcps->renew = false;
  114. dhcps->dhcps_lease_time = DHCPS_LEASE_TIME_DEF;
  115. dhcps->dhcps_offer = 0xFF;
  116. dhcps->dhcps_dns = 0x00;
  117. dhcps->dhcps_pcb = NULL;
  118. dhcps->state = DHCPS_HANDLE_CREATED;
  119. return dhcps;
  120. }
  121. void dhcps_delete(dhcps_t *dhcps)
  122. {
  123. if (dhcps) {
  124. if (dhcps->state == DHCPS_HANDLE_STARTED) {
  125. // if the dhcp-server has started already, we have to postpone the deletion
  126. dhcps->state = DHCPS_HANDLE_DELETE_PENDING;
  127. } else {
  128. // otherwise, we're free to delete the handle immediately
  129. free(dhcps);
  130. }
  131. }
  132. }
  133. static void get_ip_info(struct netif * netif, ip_info_t *ip_info)
  134. {
  135. if (netif != NULL && netif_is_up(netif)) {
  136. ip4_addr_set(&ip_info->ip, ip_2_ip4(&netif->ip_addr));
  137. ip4_addr_set(&ip_info->netmask, ip_2_ip4(&netif->netmask));
  138. ip4_addr_set(&ip_info->gw, ip_2_ip4(&netif->gw));
  139. }
  140. }
  141. /******************************************************************************
  142. * FunctionName : dhcps_option_info
  143. * Description : get the DHCP message option info
  144. * Parameters : op_id -- DHCP message option id
  145. * opt_len -- DHCP message option length
  146. * Returns : DHCP message option addr
  147. *******************************************************************************/
  148. void *dhcps_option_info(dhcps_t *dhcps, u8_t op_id, u32_t opt_len)
  149. {
  150. void *option_arg = NULL;
  151. if (dhcps == NULL) {
  152. return NULL;
  153. }
  154. switch (op_id) {
  155. case IP_ADDRESS_LEASE_TIME:
  156. if (opt_len == sizeof(dhcps_time_t)) {
  157. option_arg = &dhcps->dhcps_lease_time;
  158. }
  159. break;
  160. case REQUESTED_IP_ADDRESS:
  161. if (opt_len == sizeof(dhcps_lease_t)) {
  162. option_arg = &dhcps->dhcps_poll;
  163. }
  164. break;
  165. case ROUTER_SOLICITATION_ADDRESS:
  166. if (opt_len == sizeof(dhcps_offer_t)) {
  167. option_arg = &dhcps->dhcps_offer;
  168. }
  169. break;
  170. case DOMAIN_NAME_SERVER:
  171. if (opt_len == sizeof(dhcps_offer_t)) {
  172. option_arg = &dhcps->dhcps_dns;
  173. }
  174. break;
  175. case SUBNET_MASK:
  176. if (opt_len == sizeof(dhcps->dhcps_mask)) {
  177. option_arg = &dhcps->dhcps_mask;
  178. }
  179. break;
  180. default:
  181. break;
  182. }
  183. return option_arg;
  184. }
  185. /******************************************************************************
  186. * FunctionName : dhcps_set_option_info
  187. * Description : set the DHCP message option info
  188. * Parameters : op_id -- DHCP message option id
  189. * opt_info -- DHCP message option info
  190. * opt_len -- DHCP message option length
  191. * Returns : none
  192. *******************************************************************************/
  193. err_t dhcps_set_option_info(dhcps_t *dhcps, u8_t op_id, void *opt_info, u32_t opt_len)
  194. {
  195. if (dhcps == NULL || opt_info == NULL) {
  196. return ERR_ARG;
  197. }
  198. switch (op_id) {
  199. case IP_ADDRESS_LEASE_TIME:
  200. if (opt_len == sizeof(dhcps_time_t)) {
  201. dhcps->dhcps_lease_time = *(dhcps_time_t *)opt_info;
  202. }
  203. break;
  204. case REQUESTED_IP_ADDRESS:
  205. if (opt_len == sizeof(dhcps_lease_t)) {
  206. dhcps->dhcps_poll = *(dhcps_lease_t *)opt_info;
  207. }
  208. break;
  209. case ROUTER_SOLICITATION_ADDRESS:
  210. if (opt_len == sizeof(dhcps_offer_t)) {
  211. dhcps->dhcps_offer = *(dhcps_offer_t *)opt_info;
  212. }
  213. break;
  214. case DOMAIN_NAME_SERVER:
  215. if (opt_len == sizeof(dhcps_offer_t)) {
  216. dhcps->dhcps_dns = *(dhcps_offer_t *)opt_info;
  217. }
  218. break;
  219. case SUBNET_MASK:
  220. if (opt_len == sizeof(dhcps->dhcps_mask)) {
  221. dhcps->dhcps_mask = *(ip4_addr_t *)opt_info;
  222. }
  223. default:
  224. break;
  225. }
  226. return ERR_OK;
  227. }
  228. /******************************************************************************
  229. * FunctionName : node_insert_to_list
  230. * Description : insert the node to the list
  231. * Parameters : phead -- the head node of the list
  232. * pinsert -- the insert node of the list
  233. * Returns : none
  234. *******************************************************************************/
  235. static void node_insert_to_list(list_node **phead, list_node *pinsert)
  236. {
  237. list_node *plist = NULL;
  238. struct dhcps_pool *pdhcps_pool = NULL;
  239. struct dhcps_pool *pdhcps_node = NULL;
  240. if (*phead == NULL) {
  241. *phead = pinsert;
  242. } else {
  243. plist = *phead;
  244. pdhcps_node = pinsert->pnode;
  245. pdhcps_pool = plist->pnode;
  246. if (pdhcps_node->ip.addr < pdhcps_pool->ip.addr) {
  247. pinsert->pnext = plist;
  248. *phead = pinsert;
  249. } else {
  250. while (plist->pnext != NULL) {
  251. pdhcps_pool = plist->pnext->pnode;
  252. if (pdhcps_node->ip.addr < pdhcps_pool->ip.addr) {
  253. pinsert->pnext = plist->pnext;
  254. plist->pnext = pinsert;
  255. break;
  256. }
  257. plist = plist->pnext;
  258. }
  259. if (plist->pnext == NULL) {
  260. plist->pnext = pinsert;
  261. }
  262. }
  263. }
  264. // pinsert->pnext = NULL;
  265. }
  266. /******************************************************************************
  267. * FunctionName : node_delete_from_list
  268. * Description : remove the node from list
  269. * Parameters : phead -- the head node of the list
  270. * pdelete -- the remove node of the list
  271. * Returns : none
  272. *******************************************************************************/
  273. void node_remove_from_list(list_node **phead, list_node *pdelete)
  274. {
  275. list_node *plist = NULL;
  276. plist = *phead;
  277. if (plist == NULL) {
  278. *phead = NULL;
  279. } else {
  280. if (plist == pdelete) {
  281. // Note: Ignoring the "use after free" warnings, as it could only happen
  282. // if the linked list contains loops
  283. *phead = plist->pnext; // NOLINT(clang-analyzer-unix.Malloc)
  284. pdelete->pnext = NULL;
  285. } else {
  286. while (plist != NULL) {
  287. if (plist->pnext == pdelete) { // NOLINT(clang-analyzer-unix.Malloc)
  288. plist->pnext = pdelete->pnext;
  289. pdelete->pnext = NULL;
  290. }
  291. plist = plist->pnext;
  292. }
  293. }
  294. }
  295. }
  296. /******************************************************************************
  297. * FunctionName : add_msg_type
  298. * Description : add TYPE option of DHCP message
  299. * Parameters : optptr -- the addr of DHCP message option
  300. * Returns : the addr of DHCP message option
  301. *******************************************************************************/
  302. static u8_t *add_msg_type(u8_t *optptr, u8_t type)
  303. {
  304. *optptr++ = DHCP_OPTION_MSG_TYPE;
  305. *optptr++ = 1;
  306. *optptr++ = type;
  307. return optptr;
  308. }
  309. /******************************************************************************
  310. * FunctionName : add_offer_options
  311. * Description : add OFFER option of DHCP message
  312. * Parameters : optptr -- the addr of DHCP message option
  313. * Returns : the addr of DHCP message option
  314. *******************************************************************************/
  315. static u8_t *add_offer_options(dhcps_t *dhcps, u8_t *optptr)
  316. {
  317. ip4_addr_t ipadd;
  318. ipadd.addr = *((u32_t *) &dhcps->server_address);
  319. *optptr++ = DHCP_OPTION_SUBNET_MASK;
  320. *optptr++ = 4;
  321. *optptr++ = ip4_addr1(&dhcps->dhcps_mask);
  322. *optptr++ = ip4_addr2(&dhcps->dhcps_mask);
  323. *optptr++ = ip4_addr3(&dhcps->dhcps_mask);
  324. *optptr++ = ip4_addr4(&dhcps->dhcps_mask);
  325. *optptr++ = DHCP_OPTION_LEASE_TIME;
  326. *optptr++ = 4;
  327. *optptr++ = ((dhcps->dhcps_lease_time * DHCPS_LEASE_UNIT) >> 24) & 0xFF;
  328. *optptr++ = ((dhcps->dhcps_lease_time * DHCPS_LEASE_UNIT) >> 16) & 0xFF;
  329. *optptr++ = ((dhcps->dhcps_lease_time * DHCPS_LEASE_UNIT) >> 8) & 0xFF;
  330. *optptr++ = ((dhcps->dhcps_lease_time * DHCPS_LEASE_UNIT) >> 0) & 0xFF;
  331. *optptr++ = DHCP_OPTION_SERVER_ID;
  332. *optptr++ = 4;
  333. *optptr++ = ip4_addr1(&ipadd);
  334. *optptr++ = ip4_addr2(&ipadd);
  335. *optptr++ = ip4_addr3(&ipadd);
  336. *optptr++ = ip4_addr4(&ipadd);
  337. if (dhcps_router_enabled(dhcps->dhcps_offer)) {
  338. ip_info_t if_ip = { 0 };
  339. get_ip_info(dhcps->dhcps_netif, &if_ip);
  340. ip4_addr_t* gw_ip = (ip4_addr_t*)&if_ip.gw;
  341. if (!ip4_addr_isany_val(*gw_ip)) {
  342. *optptr++ = DHCP_OPTION_ROUTER;
  343. *optptr++ = 4;
  344. *optptr++ = ip4_addr1(gw_ip);
  345. *optptr++ = ip4_addr2(gw_ip);
  346. *optptr++ = ip4_addr3(gw_ip);
  347. *optptr++ = ip4_addr4(gw_ip);
  348. }
  349. }
  350. *optptr++ = DHCP_OPTION_DNS_SERVER;
  351. *optptr++ = 4;
  352. if (dhcps_dns_enabled(dhcps->dhcps_dns)) {
  353. *optptr++ = ip4_addr1(&dhcps->dns_server);
  354. *optptr++ = ip4_addr2(&dhcps->dns_server);
  355. *optptr++ = ip4_addr3(&dhcps->dns_server);
  356. *optptr++ = ip4_addr4(&dhcps->dns_server);
  357. }else {
  358. *optptr++ = ip4_addr1(&ipadd);
  359. *optptr++ = ip4_addr2(&ipadd);
  360. *optptr++ = ip4_addr3(&ipadd);
  361. *optptr++ = ip4_addr4(&ipadd);
  362. }
  363. ip4_addr_t broadcast_addr = { .addr = (ipadd.addr & dhcps->dhcps_mask.addr) | ~dhcps->dhcps_mask.addr };
  364. *optptr++ = DHCP_OPTION_BROADCAST_ADDRESS;
  365. *optptr++ = 4;
  366. *optptr++ = ip4_addr1(&broadcast_addr);
  367. *optptr++ = ip4_addr2(&broadcast_addr);
  368. *optptr++ = ip4_addr3(&broadcast_addr);
  369. *optptr++ = ip4_addr4(&broadcast_addr);
  370. *optptr++ = DHCP_OPTION_INTERFACE_MTU;
  371. *optptr++ = 2;
  372. *optptr++ = 0x05;
  373. *optptr++ = 0xdc;
  374. *optptr++ = DHCP_OPTION_PERFORM_ROUTER_DISCOVERY;
  375. *optptr++ = 1;
  376. *optptr++ = 0x00;
  377. *optptr++ = 43;
  378. *optptr++ = 6;
  379. *optptr++ = 0x01;
  380. *optptr++ = 4;
  381. *optptr++ = 0x00;
  382. *optptr++ = 0x00;
  383. *optptr++ = 0x00;
  384. *optptr++ = 0x02;
  385. return optptr;
  386. }
  387. /******************************************************************************
  388. * FunctionName : add_end
  389. * Description : add end option of DHCP message
  390. * Parameters : optptr -- the addr of DHCP message option
  391. * Returns : the addr of DHCP message option
  392. *******************************************************************************/
  393. static u8_t *add_end(u8_t *optptr)
  394. {
  395. *optptr++ = DHCP_OPTION_END;
  396. return optptr;
  397. }
  398. /******************************************************************************
  399. * FunctionName : create_msg
  400. * Description : create response message
  401. * Parameters : m -- DHCP message info
  402. * Returns : none
  403. *******************************************************************************/
  404. static void create_msg(dhcps_t *dhcps, struct dhcps_msg *m)
  405. {
  406. ip4_addr_t client;
  407. client.addr = *((uint32_t *) &dhcps->client_address);
  408. m->op = DHCP_REPLY;
  409. m->htype = DHCP_HTYPE_ETHERNET;
  410. m->hlen = 6;
  411. m->hops = 0;
  412. // os_memcpy((char *) xid, (char *) m->xid, sizeof(m->xid));
  413. m->secs = 0;
  414. m->flags = htons(BOOTP_BROADCAST);
  415. memcpy((char *) m->yiaddr, (char *) &client.addr, sizeof(m->yiaddr));
  416. memset((char *) m->ciaddr, 0, sizeof(m->ciaddr));
  417. memset((char *) m->siaddr, 0, sizeof(m->siaddr));
  418. memset((char *) m->giaddr, 0, sizeof(m->giaddr));
  419. memset((char *) m->sname, 0, sizeof(m->sname));
  420. memset((char *) m->file, 0, sizeof(m->file));
  421. memset((char *) m->options, 0, sizeof(m->options));
  422. u32_t magic_cookie_temp = magic_cookie;
  423. memcpy((char *) m->options, &magic_cookie_temp, sizeof(magic_cookie_temp));
  424. }
  425. struct pbuf * dhcps_pbuf_alloc(u16_t len)
  426. {
  427. u16_t mlen = sizeof(struct dhcps_msg);
  428. if (len > mlen) {
  429. #if DHCPS_DEBUG
  430. DHCPS_LOG("dhcps: len=%d mlen=%d", len, mlen);
  431. #endif
  432. mlen = len;
  433. }
  434. return pbuf_alloc(PBUF_TRANSPORT, mlen, PBUF_RAM);
  435. }
  436. /******************************************************************************
  437. * FunctionName : send_offer
  438. * Description : DHCP message OFFER Response
  439. * Parameters : m -- DHCP message info
  440. * Returns : none
  441. *******************************************************************************/
  442. static void send_offer(dhcps_t *dhcps, struct dhcps_msg *m, u16_t len)
  443. {
  444. u8_t *end;
  445. struct pbuf *p, *q;
  446. u8_t *data;
  447. u16_t cnt = 0;
  448. u16_t i;
  449. #if DHCPS_DEBUG
  450. err_t SendOffer_err_t;
  451. #endif
  452. create_msg(dhcps, m);
  453. end = add_msg_type(&m->options[4], DHCPOFFER);
  454. end = add_offer_options(dhcps, end);
  455. LWIP_HOOK_DHCPS_POST_APPEND_OPTS(dhcps->netif, dhcps, DHCPOFFER, &end)
  456. end = add_end(end);
  457. p = dhcps_pbuf_alloc(len);
  458. #if DHCPS_DEBUG
  459. DHCPS_LOG("udhcp: send_offer>>p->ref = %d\n", p->ref);
  460. #endif
  461. if (p != NULL) {
  462. #if DHCPS_DEBUG
  463. DHCPS_LOG("dhcps: send_offer>>pbuf_alloc succeed\n");
  464. DHCPS_LOG("dhcps: send_offer>>p->tot_len = %d\n", p->tot_len);
  465. DHCPS_LOG("dhcps: send_offer>>p->len = %d\n", p->len);
  466. #endif
  467. q = p;
  468. while (q != NULL) {
  469. data = (u8_t *)q->payload;
  470. for (i = 0; i < q->len; i++) {
  471. data[i] = ((u8_t *) m)[cnt++];
  472. #if DHCPS_DEBUG
  473. DHCPS_LOG("%02x ", data[i]);
  474. if ((i + 1) % 16 == 0) {
  475. DHCPS_LOG("\n");
  476. }
  477. #endif
  478. }
  479. q = q->next;
  480. }
  481. } else {
  482. #if DHCPS_DEBUG
  483. DHCPS_LOG("dhcps: send_offer>>pbuf_alloc failed\n");
  484. #endif
  485. return;
  486. }
  487. ip_addr_t ip_temp = IPADDR4_INIT(0x0);
  488. ip4_addr_set(ip_2_ip4(&ip_temp), &dhcps->broadcast_dhcps);
  489. #if DHCPS_DEBUG
  490. SendOffer_err_t = udp_sendto(pcb_dhcps, p, &ip_temp, DHCPS_CLIENT_PORT);
  491. DHCPS_LOG("dhcps: send_offer>>udp_sendto result %x\n", SendOffer_err_t);
  492. #else
  493. udp_sendto(dhcps->dhcps_pcb, p, &ip_temp, DHCPS_CLIENT_PORT);
  494. #endif
  495. if (p->ref != 0) {
  496. #if DHCPS_DEBUG
  497. DHCPS_LOG("udhcp: send_offer>>free pbuf\n");
  498. #endif
  499. pbuf_free(p);
  500. }
  501. }
  502. /******************************************************************************
  503. * FunctionName : send_nak
  504. * Description : DHCP message NACK Response
  505. * Parameters : m -- DHCP message info
  506. * Returns : none
  507. *******************************************************************************/
  508. static void send_nak(dhcps_t *dhcps, struct dhcps_msg *m, u16_t len)
  509. {
  510. u8_t *end;
  511. struct pbuf *p, *q;
  512. u8_t *data;
  513. u16_t cnt = 0;
  514. u16_t i;
  515. #if DHCPS_DEBUG
  516. err_t SendNak_err_t;
  517. #endif
  518. create_msg(dhcps, m);
  519. end = add_msg_type(&m->options[4], DHCPNAK);
  520. LWIP_HOOK_DHCPS_POST_APPEND_OPTS(dhcps->netif, dhcps, DHCPNAK, &end)
  521. end = add_end(end);
  522. p = dhcps_pbuf_alloc(len);
  523. #if DHCPS_DEBUG
  524. DHCPS_LOG("udhcp: send_nak>>p->ref = %d\n", p->ref);
  525. #endif
  526. if (p != NULL) {
  527. #if DHCPS_DEBUG
  528. DHCPS_LOG("dhcps: send_nak>>pbuf_alloc succeed\n");
  529. DHCPS_LOG("dhcps: send_nak>>p->tot_len = %d\n", p->tot_len);
  530. DHCPS_LOG("dhcps: send_nak>>p->len = %d\n", p->len);
  531. #endif
  532. q = p;
  533. while (q != NULL) {
  534. data = (u8_t *)q->payload;
  535. for (i = 0; i < q->len; i++) {
  536. data[i] = ((u8_t *) m)[cnt++];
  537. #if DHCPS_DEBUG
  538. DHCPS_LOG("%02x ", data[i]);
  539. if ((i + 1) % 16 == 0) {
  540. DHCPS_LOG("\n");
  541. }
  542. #endif
  543. }
  544. q = q->next;
  545. }
  546. } else {
  547. #if DHCPS_DEBUG
  548. DHCPS_LOG("dhcps: send_nak>>pbuf_alloc failed\n");
  549. #endif
  550. return;
  551. }
  552. ip_addr_t ip_temp = IPADDR4_INIT(0x0);
  553. ip4_addr_set(ip_2_ip4(&ip_temp), &dhcps->broadcast_dhcps);
  554. #if DHCPS_DEBUG
  555. SendNak_err_t = udp_sendto(pcb_dhcps, p, &ip_temp, DHCPS_CLIENT_PORT);
  556. DHCPS_LOG("dhcps: send_nak>>udp_sendto result %x\n", SendNak_err_t);
  557. #else
  558. udp_sendto(dhcps->dhcps_pcb, p, &ip_temp, DHCPS_CLIENT_PORT);
  559. #endif
  560. if (p->ref != 0) {
  561. #if DHCPS_DEBUG
  562. DHCPS_LOG("udhcp: send_nak>>free pbuf\n");
  563. #endif
  564. pbuf_free(p);
  565. }
  566. }
  567. /******************************************************************************
  568. * FunctionName : send_ack
  569. * Description : DHCP message ACK Response
  570. * Parameters : m -- DHCP message info
  571. * Returns : none
  572. *******************************************************************************/
  573. static void send_ack(dhcps_t *dhcps, struct dhcps_msg *m, u16_t len)
  574. {
  575. u8_t *end;
  576. struct pbuf *p, *q;
  577. u8_t *data;
  578. u16_t cnt = 0;
  579. u16_t i;
  580. err_t SendAck_err_t;
  581. create_msg(dhcps, m);
  582. end = add_msg_type(&m->options[4], DHCPACK);
  583. end = add_offer_options(dhcps, end);
  584. LWIP_HOOK_DHCPS_POST_APPEND_OPTS(dhcps->netif, dhcps, DHCPACK, &end)
  585. end = add_end(end);
  586. p = dhcps_pbuf_alloc(len);
  587. #if DHCPS_DEBUG
  588. DHCPS_LOG("udhcp: send_ack>>p->ref = %d\n", p->ref);
  589. #endif
  590. if (p != NULL) {
  591. #if DHCPS_DEBUG
  592. DHCPS_LOG("dhcps: send_ack>>pbuf_alloc succeed\n");
  593. DHCPS_LOG("dhcps: send_ack>>p->tot_len = %d\n", p->tot_len);
  594. DHCPS_LOG("dhcps: send_ack>>p->len = %d\n", p->len);
  595. #endif
  596. q = p;
  597. while (q != NULL) {
  598. data = (u8_t *)q->payload;
  599. for (i = 0; i < q->len; i++) {
  600. data[i] = ((u8_t *) m)[cnt++];
  601. #if DHCPS_DEBUG
  602. DHCPS_LOG("%02x ", data[i]);
  603. if ((i + 1) % 16 == 0) {
  604. DHCPS_LOG("\n");
  605. }
  606. #endif
  607. }
  608. q = q->next;
  609. }
  610. } else {
  611. #if DHCPS_DEBUG
  612. DHCPS_LOG("dhcps: send_ack>>pbuf_alloc failed\n");
  613. #endif
  614. return;
  615. }
  616. ip_addr_t ip_temp = IPADDR4_INIT(0x0);
  617. ip4_addr_set(ip_2_ip4(&ip_temp), &dhcps->broadcast_dhcps);
  618. SendAck_err_t = udp_sendto(dhcps->dhcps_pcb, p, &ip_temp, DHCPS_CLIENT_PORT);
  619. #if DHCPS_DEBUG
  620. DHCPS_LOG("dhcps: send_ack>>udp_sendto result %x\n", SendAck_err_t);
  621. #endif
  622. if (SendAck_err_t == ERR_OK) {
  623. dhcps->dhcps_cb(dhcps->dhcps_cb_arg, m->yiaddr, m->chaddr);
  624. }
  625. if (p->ref != 0) {
  626. #if DHCPS_DEBUG
  627. DHCPS_LOG("udhcp: send_ack>>free pbuf\n");
  628. #endif
  629. pbuf_free(p);
  630. }
  631. }
  632. /******************************************************************************
  633. * FunctionName : parse_options
  634. * Description : parse DHCP message options
  635. * Parameters : optptr -- DHCP message option info
  636. * len -- DHCP message option length
  637. * Returns : none
  638. *******************************************************************************/
  639. static u8_t parse_options(dhcps_t *dhcps, u8_t *optptr, s16_t len)
  640. {
  641. ip4_addr_t client;
  642. bool is_dhcp_parse_end = false;
  643. struct dhcps_state s;
  644. client.addr = *((uint32_t *) &dhcps->client_address);
  645. u8_t *end = optptr + len;
  646. u16_t type = 0;
  647. s.state = DHCPS_STATE_IDLE;
  648. while (optptr < end) {
  649. #if DHCPS_DEBUG
  650. DHCPS_LOG("dhcps: (s16_t)*optptr = %d\n", (s16_t)*optptr);
  651. #endif
  652. switch ((s16_t) *optptr) {
  653. case DHCP_OPTION_MSG_TYPE: //53
  654. type = *(optptr + 2);
  655. break;
  656. case DHCP_OPTION_REQ_IPADDR://50
  657. if (memcmp((char *) &client.addr, (char *) optptr + 2, 4) == 0) {
  658. #if DHCPS_DEBUG
  659. DHCPS_LOG("dhcps: DHCP_OPTION_REQ_IPADDR = 0 ok\n");
  660. #endif
  661. s.state = DHCPS_STATE_ACK;
  662. } else {
  663. #if DHCPS_DEBUG
  664. DHCPS_LOG("dhcps: DHCP_OPTION_REQ_IPADDR != 0 err\n");
  665. #endif
  666. s.state = DHCPS_STATE_NAK;
  667. }
  668. break;
  669. case DHCP_OPTION_END: {
  670. is_dhcp_parse_end = true;
  671. }
  672. break;
  673. }
  674. if (is_dhcp_parse_end) {
  675. break;
  676. }
  677. optptr += optptr[1] + 2;
  678. }
  679. switch (type) {
  680. case DHCPDISCOVER://1
  681. s.state = DHCPS_STATE_OFFER;
  682. #if DHCPS_DEBUG
  683. DHCPS_LOG("dhcps: DHCPD_STATE_OFFER\n");
  684. #endif
  685. break;
  686. case DHCPREQUEST://3
  687. if (!(s.state == DHCPS_STATE_ACK || s.state == DHCPS_STATE_NAK)) {
  688. if (dhcps->renew == true) {
  689. s.state = DHCPS_STATE_ACK;
  690. } else {
  691. s.state = DHCPS_STATE_NAK;
  692. }
  693. #if DHCPS_DEBUG
  694. DHCPS_LOG("dhcps: DHCPD_STATE_NAK\n");
  695. #endif
  696. }
  697. break;
  698. case DHCPDECLINE://4
  699. s.state = DHCPS_STATE_IDLE;
  700. #if DHCPS_DEBUG
  701. DHCPS_LOG("dhcps: DHCPD_STATE_IDLE\n");
  702. #endif
  703. break;
  704. case DHCPRELEASE://7
  705. s.state = DHCPS_STATE_RELEASE;
  706. #if DHCPS_DEBUG
  707. DHCPS_LOG("dhcps: DHCPD_STATE_IDLE\n");
  708. #endif
  709. break;
  710. }
  711. #if DHCPS_DEBUG
  712. DHCPS_LOG("dhcps: return s.state = %d\n", s.state);
  713. #endif
  714. return s.state;
  715. }
  716. /******************************************************************************
  717. * FunctionName : parse_msg
  718. * Description : parse DHCP message from netif
  719. * Parameters : m -- DHCP message info
  720. * len -- DHCP message length
  721. * Returns : DHCP message type
  722. *******************************************************************************/
  723. static s16_t parse_msg(dhcps_t *dhcps, struct dhcps_msg *m, u16_t len)
  724. {
  725. u32_t lease_timer = (dhcps->dhcps_lease_time * DHCPS_LEASE_UNIT)/DHCPS_COARSE_TIMER_SECS;
  726. if (memcmp((char *)m->options, &magic_cookie, sizeof(magic_cookie)) == 0) {
  727. #if DHCPS_DEBUG
  728. DHCPS_LOG("dhcps: len = %d\n", len);
  729. #endif
  730. ip4_addr_t addr_tmp;
  731. struct dhcps_pool *pdhcps_pool = NULL;
  732. list_node *pnode = NULL;
  733. list_node *pback_node = NULL;
  734. ip4_addr_t first_address;
  735. bool flag = false;
  736. first_address.addr = dhcps->dhcps_poll.start_ip.addr;
  737. dhcps->client_address.addr = dhcps->client_address_plus.addr;
  738. dhcps->renew = false;
  739. if (dhcps->plist != NULL) {
  740. for (pback_node = dhcps->plist; pback_node != NULL; pback_node = pback_node->pnext) {
  741. pdhcps_pool = pback_node->pnode;
  742. if (memcmp(pdhcps_pool->mac, m->chaddr, sizeof(pdhcps_pool->mac)) == 0) {
  743. if (memcmp(&pdhcps_pool->ip.addr, m->ciaddr, sizeof(pdhcps_pool->ip.addr)) == 0) {
  744. dhcps->renew = true;
  745. }
  746. dhcps->client_address.addr = pdhcps_pool->ip.addr;
  747. pdhcps_pool->lease_timer = lease_timer;
  748. pnode = pback_node;
  749. goto POOL_CHECK;
  750. } else if (pdhcps_pool->ip.addr == dhcps->client_address_plus.addr) {
  751. addr_tmp.addr = htonl(dhcps->client_address_plus.addr);
  752. addr_tmp.addr++;
  753. dhcps->client_address_plus.addr = htonl(addr_tmp.addr);
  754. dhcps->client_address.addr = dhcps->client_address_plus.addr;
  755. }
  756. if (flag == false) { // search the fisrt unused ip
  757. if (first_address.addr < pdhcps_pool->ip.addr) {
  758. flag = true;
  759. } else {
  760. addr_tmp.addr = htonl(first_address.addr);
  761. addr_tmp.addr++;
  762. first_address.addr = htonl(addr_tmp.addr);
  763. }
  764. }
  765. }
  766. } else {
  767. dhcps->client_address.addr = dhcps->dhcps_poll.start_ip.addr;
  768. }
  769. if (dhcps->client_address_plus.addr > dhcps->dhcps_poll.end_ip.addr) {
  770. dhcps->client_address.addr = first_address.addr;
  771. }
  772. if (dhcps->client_address.addr > dhcps->dhcps_poll.end_ip.addr) {
  773. dhcps->client_address_plus.addr = dhcps->dhcps_poll.start_ip.addr;
  774. pdhcps_pool = NULL;
  775. pnode = NULL;
  776. } else {
  777. pdhcps_pool = (struct dhcps_pool *)mem_calloc(1, sizeof(struct dhcps_pool));
  778. pdhcps_pool->ip.addr = dhcps->client_address.addr;
  779. memcpy(pdhcps_pool->mac, m->chaddr, sizeof(pdhcps_pool->mac));
  780. pdhcps_pool->lease_timer = lease_timer;
  781. pnode = (list_node *)mem_calloc(1, sizeof(list_node));
  782. pnode->pnode = pdhcps_pool;
  783. pnode->pnext = NULL;
  784. node_insert_to_list(&dhcps->plist, pnode);
  785. if (dhcps->client_address.addr == dhcps->dhcps_poll.end_ip.addr) {
  786. dhcps->client_address_plus.addr = dhcps->dhcps_poll.start_ip.addr;
  787. } else {
  788. addr_tmp.addr = htonl(dhcps->client_address.addr);
  789. addr_tmp.addr++;
  790. dhcps->client_address_plus.addr = htonl(addr_tmp.addr);
  791. }
  792. }
  793. POOL_CHECK:
  794. if ((dhcps->client_address.addr > dhcps->dhcps_poll.end_ip.addr) || (ip4_addr_isany(&dhcps->client_address))) {
  795. if (pnode != NULL) {
  796. node_remove_from_list(&dhcps->plist, pnode);
  797. free(pnode);
  798. pnode = NULL;
  799. }
  800. if (pdhcps_pool != NULL) {
  801. free(pdhcps_pool);
  802. pdhcps_pool = NULL;
  803. }
  804. return 4;
  805. }
  806. s16_t ret = parse_options(dhcps, &m->options[4], len);;
  807. if (ret == DHCPS_STATE_RELEASE || ret == DHCPS_STATE_NAK) {
  808. if (pnode != NULL) {
  809. node_remove_from_list(&dhcps->plist, pnode);
  810. free(pnode);
  811. pnode = NULL;
  812. }
  813. if (pdhcps_pool != NULL) {
  814. free(pdhcps_pool);
  815. pdhcps_pool = NULL;
  816. }
  817. memset(&dhcps->client_address, 0x0, sizeof(dhcps->client_address));
  818. }
  819. #if DHCPS_DEBUG
  820. DHCPS_LOG("dhcps: xid changed\n");
  821. DHCPS_LOG("dhcps: client_address.addr = %x\n", client_address.addr);
  822. #endif
  823. return ret;
  824. }
  825. return 0;
  826. }
  827. /******************************************************************************
  828. * FunctionName : handle_dhcp
  829. * Description : If an incoming DHCP message is in response to us, then trigger the state machine
  830. * Parameters : arg -- arg user supplied argument (udp_pcb.recv_arg)
  831. * pcb -- the udp_pcb which received data
  832. * p -- the packet buffer that was received
  833. * addr -- the remote IP address from which the packet was received
  834. * port -- the remote port from which the packet was received
  835. * Returns : none
  836. *******************************************************************************/
  837. static void handle_dhcp(void *arg,
  838. struct udp_pcb *pcb,
  839. struct pbuf *p,
  840. const ip_addr_t *addr,
  841. u16_t port)
  842. {
  843. struct dhcps_t *dhcps = arg;
  844. struct dhcps_msg *pmsg_dhcps = NULL;
  845. s16_t tlen, malloc_len;
  846. u16_t i;
  847. u16_t dhcps_msg_cnt = 0;
  848. u8_t *p_dhcps_msg = NULL;
  849. u8_t *data;
  850. s16_t state;
  851. #if DHCPS_DEBUG
  852. DHCPS_LOG("dhcps: handle_dhcp-> receive a packet\n");
  853. #endif
  854. if (p == NULL) {
  855. return;
  856. }
  857. malloc_len = sizeof(struct dhcps_msg);
  858. #if DHCPS_DEBUG
  859. DHCPS_LOG("dhcps: handle_dhcp malloc_len=%d rx_len=%d", malloc_len, p->tot_len);
  860. #endif
  861. if (malloc_len < p->tot_len) {
  862. malloc_len = p->tot_len;
  863. }
  864. pmsg_dhcps = (struct dhcps_msg *)mem_calloc(1, malloc_len);
  865. if (NULL == pmsg_dhcps) {
  866. pbuf_free(p);
  867. return;
  868. }
  869. p_dhcps_msg = (u8_t *)pmsg_dhcps;
  870. tlen = p->tot_len;
  871. data = p->payload;
  872. #if DHCPS_DEBUG
  873. DHCPS_LOG("dhcps: handle_dhcp-> p->tot_len = %d\n", tlen);
  874. DHCPS_LOG("dhcps: handle_dhcp-> p->len = %d\n", p->len);
  875. #endif
  876. for (i = 0; i < p->len; i++) {
  877. p_dhcps_msg[dhcps_msg_cnt++] = data[i];
  878. #if DHCPS_DEBUG
  879. DHCPS_LOG("%02x ", data[i]);
  880. if ((i + 1) % 16 == 0) {
  881. DHCPS_LOG("\n");
  882. }
  883. #endif
  884. }
  885. if (p->next != NULL) {
  886. #if DHCPS_DEBUG
  887. DHCPS_LOG("dhcps: handle_dhcp-> p->next != NULL\n");
  888. DHCPS_LOG("dhcps: handle_dhcp-> p->next->tot_len = %d\n", p->next->tot_len);
  889. DHCPS_LOG("dhcps: handle_dhcp-> p->next->len = %d\n", p->next->len);
  890. #endif
  891. data = p->next->payload;
  892. for (i = 0; i < p->next->len; i++) {
  893. p_dhcps_msg[dhcps_msg_cnt++] = data[i];
  894. #if DHCPS_DEBUG
  895. DHCPS_LOG("%02x ", data[i]);
  896. if ((i + 1) % 16 == 0) {
  897. DHCPS_LOG("\n");
  898. }
  899. #endif
  900. }
  901. }
  902. #if DHCPS_DEBUG
  903. DHCPS_LOG("dhcps: handle_dhcp-> parse_msg(p)\n");
  904. #endif
  905. state = parse_msg(dhcps, pmsg_dhcps, tlen - 240);
  906. #ifdef LWIP_HOOK_DHCPS_POST_STATE
  907. state = LWIP_HOOK_DHCPS_POST_STATE(pmsg_dhcps, malloc_len, state);
  908. #endif /* LWIP_HOOK_DHCPS_POST_STATE */
  909. switch (state) {
  910. case DHCPS_STATE_OFFER://1
  911. #if DHCPS_DEBUG
  912. DHCPS_LOG("dhcps: handle_dhcp-> DHCPD_STATE_OFFER\n");
  913. #endif
  914. send_offer(dhcps, pmsg_dhcps, malloc_len);
  915. break;
  916. case DHCPS_STATE_ACK://3
  917. #if DHCPS_DEBUG
  918. DHCPS_LOG("dhcps: handle_dhcp-> DHCPD_STATE_ACK\n");
  919. #endif
  920. send_ack(dhcps, pmsg_dhcps, malloc_len);
  921. break;
  922. case DHCPS_STATE_NAK://4
  923. #if DHCPS_DEBUG
  924. DHCPS_LOG("dhcps: handle_dhcp-> DHCPD_STATE_NAK\n");
  925. #endif
  926. send_nak(dhcps, pmsg_dhcps, malloc_len);
  927. break;
  928. default :
  929. break;
  930. }
  931. #if DHCPS_DEBUG
  932. DHCPS_LOG("dhcps: handle_dhcp-> pbuf_free(p)\n");
  933. #endif
  934. pbuf_free(p);
  935. free(pmsg_dhcps);
  936. pmsg_dhcps = NULL;
  937. }
  938. /******************************************************************************
  939. * FunctionName : dhcps_poll_set
  940. * Description : set ip poll from start to end for station
  941. * Parameters : ip -- The current ip addr
  942. * Returns : none
  943. *******************************************************************************/
  944. static void dhcps_poll_set(dhcps_t *dhcps, u32_t ip)
  945. {
  946. u32_t softap_ip = 0, local_ip = 0;
  947. u32_t start_ip = 0;
  948. u32_t end_ip = 0;
  949. dhcps_lease_t *dhcps_poll = &dhcps->dhcps_poll;
  950. if (dhcps_poll->enable == true) {
  951. softap_ip = htonl(ip);
  952. start_ip = htonl(dhcps_poll->start_ip.addr);
  953. end_ip = htonl(dhcps_poll->end_ip.addr);
  954. /*config ip information can't contain local ip*/
  955. if ((start_ip <= softap_ip) && (softap_ip <= end_ip)) {
  956. dhcps_poll->enable = false;
  957. } else {
  958. /*config ip information must be in the same segment as the local ip*/
  959. softap_ip >>= 8;
  960. if (((start_ip >> 8 != softap_ip) || (end_ip >> 8 != softap_ip))
  961. || (end_ip - start_ip > DHCPS_MAX_LEASE)) {
  962. dhcps_poll->enable = false;
  963. }
  964. }
  965. }
  966. if (dhcps_poll->enable == false) {
  967. local_ip = softap_ip = htonl(ip);
  968. softap_ip &= 0xFFFFFF00;
  969. local_ip &= 0xFF;
  970. if (local_ip >= 0x80) {
  971. local_ip -= DHCPS_MAX_LEASE;
  972. } else {
  973. local_ip ++;
  974. }
  975. bzero(dhcps_poll, sizeof(*dhcps_poll));
  976. dhcps_poll->start_ip.addr = softap_ip | local_ip;
  977. dhcps_poll->end_ip.addr = softap_ip | (local_ip + DHCPS_MAX_LEASE - 1);
  978. dhcps_poll->start_ip.addr = htonl(dhcps_poll->start_ip.addr);
  979. dhcps_poll->end_ip.addr = htonl(dhcps_poll->end_ip.addr);
  980. }
  981. }
  982. /******************************************************************************
  983. * FunctionName : dhcps_set_new_lease_cb
  984. * Description : set callback for dhcp server when it assign an IP
  985. * to the connected dhcp client
  986. * Parameters : cb -- callback for dhcp server
  987. * Returns : ERR_OK on success
  988. *******************************************************************************/
  989. err_t dhcps_set_new_lease_cb(dhcps_t *dhcps, dhcps_cb_t cb, void* cb_arg)
  990. {
  991. if (dhcps == NULL) {
  992. return ERR_ARG;
  993. }
  994. dhcps->dhcps_cb = cb;
  995. dhcps->dhcps_cb_arg = cb_arg;
  996. return ERR_OK;
  997. }
  998. /******************************************************************************
  999. * FunctionName : dhcps_start
  1000. * Description : start dhcp server function
  1001. * Parameters : netif -- The current netif addr
  1002. * : info -- The current ip info
  1003. * Returns : none
  1004. *******************************************************************************/
  1005. err_t dhcps_start(dhcps_t *dhcps, struct netif *netif, ip4_addr_t ip)
  1006. {
  1007. if (dhcps == NULL || netif == NULL) {
  1008. return ERR_ARG;
  1009. }
  1010. dhcps->dhcps_netif = netif;
  1011. if (dhcps->dhcps_pcb != NULL) {
  1012. udp_remove(dhcps->dhcps_pcb);
  1013. }
  1014. dhcps->dhcps_pcb = udp_new();
  1015. if (dhcps->dhcps_pcb == NULL || ip4_addr_isany_val(ip)) {
  1016. printf("dhcps_start(): could not obtain pcb\n");
  1017. return ERR_ARG;
  1018. }
  1019. IP4_ADDR(&dhcps->broadcast_dhcps, 255, 255, 255, 255);
  1020. dhcps->server_address.addr = ip.addr;
  1021. dhcps_poll_set(dhcps, dhcps->server_address.addr);
  1022. dhcps->client_address_plus.addr = dhcps->dhcps_poll.start_ip.addr;
  1023. udp_bind(dhcps->dhcps_pcb, &netif->ip_addr, DHCPS_SERVER_PORT);
  1024. udp_recv(dhcps->dhcps_pcb, handle_dhcp, dhcps);
  1025. #if DHCPS_DEBUG
  1026. DHCPS_LOG("dhcps:dhcps_start->udp_recv function Set a receive callback handle_dhcp for UDP_PCB pcb_dhcps\n");
  1027. #endif
  1028. dhcps->state = DHCPS_HANDLE_STARTED;
  1029. sys_timeout(DHCP_COARSE_TIMER_MSECS, dhcps_tmr, dhcps);
  1030. return ERR_OK;
  1031. }
  1032. /******************************************************************************
  1033. * FunctionName : dhcps_stop
  1034. * Description : stop dhcp server function
  1035. * Parameters : netif -- The current netif addr
  1036. * Returns : none
  1037. *******************************************************************************/
  1038. err_t dhcps_stop(dhcps_t *dhcps, struct netif *netif)
  1039. {
  1040. if (dhcps == NULL || netif == NULL || dhcps->dhcps_netif != netif) {
  1041. #if DHCPS_DEBUG
  1042. DHCPS_LOG("dhcps_stop: netif is NULL or invalid\n");
  1043. #endif
  1044. return ERR_ARG;
  1045. }
  1046. if (dhcps->dhcps_pcb != NULL) {
  1047. udp_disconnect(dhcps->dhcps_pcb);
  1048. udp_remove(dhcps->dhcps_pcb);
  1049. dhcps->dhcps_pcb = NULL;
  1050. }
  1051. list_node *pnode = NULL;
  1052. list_node *pback_node = NULL;
  1053. pnode = dhcps->plist;
  1054. while (pnode != NULL) {
  1055. pback_node = pnode;
  1056. pnode = pback_node->pnext;
  1057. node_remove_from_list(&dhcps->plist, pback_node);
  1058. free(pback_node->pnode);
  1059. pback_node->pnode = NULL;
  1060. free(pback_node);
  1061. pback_node = NULL;
  1062. }
  1063. sys_untimeout(dhcps_tmr, dhcps);
  1064. dhcps->state = DHCPS_HANDLE_STOPPED;
  1065. return ERR_OK;
  1066. }
  1067. /******************************************************************************
  1068. * FunctionName : kill_oldest_dhcps_pool
  1069. * Description : remove the oldest node from list
  1070. * Parameters : none
  1071. * Returns : none
  1072. *******************************************************************************/
  1073. static void kill_oldest_dhcps_pool(dhcps_t *dhcps)
  1074. {
  1075. list_node *pre = NULL, *p = NULL;
  1076. list_node *minpre = NULL, *minp = NULL;
  1077. struct dhcps_pool *pdhcps_pool = NULL, *pmin_pool = NULL;
  1078. pre = dhcps->plist;
  1079. assert(pre != NULL && pre->pnext != NULL); // Expect the list to have at least 2 nodes
  1080. p = pre->pnext;
  1081. minpre = pre;
  1082. minp = p;
  1083. while (p != NULL) {
  1084. pdhcps_pool = p->pnode;
  1085. pmin_pool = minp->pnode;
  1086. if (pdhcps_pool->lease_timer < pmin_pool->lease_timer) {
  1087. minp = p;
  1088. minpre = pre;
  1089. }
  1090. pre = p;
  1091. p = p->pnext;
  1092. }
  1093. minpre->pnext = minp->pnext;
  1094. free(minp->pnode);
  1095. minp->pnode = NULL;
  1096. free(minp);
  1097. minp = NULL;
  1098. }
  1099. /******************************************************************************
  1100. * FunctionName : dhcps_coarse_tmr
  1101. * Description : the lease time count
  1102. * Parameters : none
  1103. * Returns : none
  1104. *******************************************************************************/
  1105. static void dhcps_tmr(void *arg)
  1106. {
  1107. dhcps_t *dhcps = arg;
  1108. dhcps_handle_state state = dhcps->state;
  1109. if (state == DHCPS_HANDLE_DELETE_PENDING) {
  1110. free(dhcps);
  1111. return;
  1112. }
  1113. if (state != DHCPS_HANDLE_STARTED) {
  1114. return;
  1115. }
  1116. sys_timeout(DHCP_COARSE_TIMER_MSECS, dhcps_tmr, dhcps);
  1117. u8_t num_dhcps_pool = 0;
  1118. list_node *pback_node = NULL;
  1119. list_node *pnode = NULL;
  1120. struct dhcps_pool *pdhcps_pool = NULL;
  1121. pnode = dhcps->plist;
  1122. while (pnode != NULL) {
  1123. pdhcps_pool = pnode->pnode;
  1124. pdhcps_pool->lease_timer --;
  1125. if (pdhcps_pool->lease_timer == 0) {
  1126. pback_node = pnode;
  1127. pnode = pback_node->pnext;
  1128. node_remove_from_list(&dhcps->plist, pback_node);
  1129. free(pback_node->pnode);
  1130. pback_node->pnode = NULL;
  1131. free(pback_node);
  1132. pback_node = NULL;
  1133. } else {
  1134. pnode = pnode ->pnext;
  1135. num_dhcps_pool ++;
  1136. }
  1137. }
  1138. if (num_dhcps_pool > MAX_STATION_NUM) {
  1139. kill_oldest_dhcps_pool(dhcps);
  1140. }
  1141. }
  1142. /******************************************************************************
  1143. * FunctionName : dhcp_search_ip_on_mac
  1144. * Description : Search ip address based on mac address
  1145. * Parameters : mac -- The MAC addr
  1146. * ip -- The IP info
  1147. * Returns : true or false
  1148. *******************************************************************************/
  1149. bool dhcp_search_ip_on_mac(dhcps_t *dhcps, u8_t *mac, ip4_addr_t *ip)
  1150. {
  1151. struct dhcps_pool *pdhcps_pool = NULL;
  1152. list_node *pback_node = NULL;
  1153. bool ret = false;
  1154. if (dhcps == NULL) {
  1155. return false;
  1156. }
  1157. for (pback_node = dhcps->plist; pback_node != NULL; pback_node = pback_node->pnext) {
  1158. pdhcps_pool = pback_node->pnode;
  1159. if (memcmp(pdhcps_pool->mac, mac, sizeof(pdhcps_pool->mac)) == 0) {
  1160. memcpy(&ip->addr, &pdhcps_pool->ip.addr, sizeof(pdhcps_pool->ip.addr));
  1161. ret = true;
  1162. break;
  1163. }
  1164. }
  1165. return ret;
  1166. }
  1167. /******************************************************************************
  1168. * FunctionName : dhcps_dns_setserver
  1169. * Description : set DNS server address for dhcpserver
  1170. * Parameters : dnsserver -- The DNS server address
  1171. * Returns : ERR_ARG if invalid handle, ERR_OK on success
  1172. *******************************************************************************/
  1173. err_t dhcps_dns_setserver(dhcps_t *dhcps, const ip_addr_t *dnsserver)
  1174. {
  1175. if (dhcps == NULL) {
  1176. return ERR_ARG;
  1177. }
  1178. if (dnsserver != NULL) {
  1179. dhcps->dns_server = *(ip_2_ip4(dnsserver));
  1180. } else {
  1181. dhcps->dns_server = *(ip_2_ip4(IP_ADDR_ANY));
  1182. }
  1183. return ERR_OK;
  1184. }
  1185. /******************************************************************************
  1186. * FunctionName : dhcps_dns_getserver
  1187. * Description : get DNS server address for dhcpserver
  1188. * Parameters : none
  1189. * Returns : ip4_addr_t
  1190. *******************************************************************************/
  1191. err_t dhcps_dns_getserver(dhcps_t *dhcps, ip4_addr_t *dnsserver)
  1192. {
  1193. if (dhcps) {
  1194. *dnsserver = dhcps->dns_server;
  1195. return ERR_OK;
  1196. }
  1197. return ERR_ARG;
  1198. }
  1199. #endif // ESP_DHCPS