dhcpserver.c 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191
  1. // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. // http://www.apache.org/licenses/LICENSE-2.0
  7. //
  8. // Unless required by applicable law or agreed to in writing, software
  9. // distributed under the License is distributed on an "AS IS" BASIS,
  10. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. // See the License for the specific language governing permissions and
  12. // limitations under the License.
  13. //#include "esp_common.h"
  14. #include <stdlib.h>
  15. #include <string.h>
  16. #include "lwip/inet.h"
  17. #include "lwip/err.h"
  18. #include "lwip/pbuf.h"
  19. #include "lwip/udp.h"
  20. #include "lwip/mem.h"
  21. #include "lwip/ip_addr.h"
  22. #include "tcpip_adapter.h"
  23. #include "apps/dhcpserver.h"
  24. #if ESP_DHCP
  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 8
  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. ////////////////////////////////////////////////////////////////////////////////////
  63. static const u32_t magic_cookie = 0x63538263;
  64. static struct udp_pcb *pcb_dhcps = NULL;
  65. static ip4_addr_t broadcast_dhcps;
  66. static ip4_addr_t server_address;
  67. static ip4_addr_t client_address; //added
  68. static ip4_addr_t client_address_plus;
  69. static list_node *plist = NULL;
  70. static bool renew = false;
  71. static dhcps_lease_t dhcps_poll;
  72. static dhcps_offer_t dhcps_offer = 0xFF;
  73. static dhcps_time_t dhcps_lease_time = DHCPS_LEASE_TIME_DEF; //minute
  74. /******************************************************************************
  75. * FunctionName : dhcps_option_info
  76. * Description : get the DHCP message option info
  77. * Parameters : op_id -- DHCP message option id
  78. * opt_len -- DHCP message option length
  79. * Returns : DHCP message option addr
  80. *******************************************************************************/
  81. void *dhcps_option_info(u8_t op_id, u32_t opt_len)
  82. {
  83. void *option_arg = NULL;
  84. switch (op_id) {
  85. case IP_ADDRESS_LEASE_TIME:
  86. if (opt_len == sizeof(dhcps_time_t)) {
  87. option_arg = &dhcps_lease_time;
  88. }
  89. break;
  90. case REQUESTED_IP_ADDRESS:
  91. if (opt_len == sizeof(dhcps_lease_t)) {
  92. option_arg = &dhcps_poll;
  93. }
  94. break;
  95. case ROUTER_SOLICITATION_ADDRESS:
  96. if (opt_len == sizeof(dhcps_offer_t)) {
  97. option_arg = &dhcps_offer;
  98. }
  99. break;
  100. default:
  101. break;
  102. }
  103. return option_arg;
  104. }
  105. /******************************************************************************
  106. * FunctionName : node_insert_to_list
  107. * Description : insert the node to the list
  108. * Parameters : phead -- the head node of the list
  109. * pinsert -- the insert node of the list
  110. * Returns : none
  111. *******************************************************************************/
  112. void node_insert_to_list(list_node **phead, list_node *pinsert)
  113. {
  114. list_node *plist = NULL;
  115. struct dhcps_pool *pdhcps_pool = NULL;
  116. struct dhcps_pool *pdhcps_node = NULL;
  117. if (*phead == NULL) {
  118. *phead = pinsert;
  119. } else {
  120. plist = *phead;
  121. pdhcps_node = pinsert->pnode;
  122. pdhcps_pool = plist->pnode;
  123. if (pdhcps_node->ip.addr < pdhcps_pool->ip.addr) {
  124. pinsert->pnext = plist;
  125. *phead = pinsert;
  126. } else {
  127. while (plist->pnext != NULL) {
  128. pdhcps_pool = plist->pnext->pnode;
  129. if (pdhcps_node->ip.addr < pdhcps_pool->ip.addr) {
  130. pinsert->pnext = plist->pnext;
  131. plist->pnext = pinsert;
  132. break;
  133. }
  134. plist = plist->pnext;
  135. }
  136. if (plist->pnext == NULL) {
  137. plist->pnext = pinsert;
  138. }
  139. }
  140. }
  141. // pinsert->pnext = NULL;
  142. }
  143. /******************************************************************************
  144. * FunctionName : node_delete_from_list
  145. * Description : remove the node from list
  146. * Parameters : phead -- the head node of the list
  147. * pdelete -- the remove node of the list
  148. * Returns : none
  149. *******************************************************************************/
  150. void node_remove_from_list(list_node **phead, list_node *pdelete)
  151. {
  152. list_node *plist = NULL;
  153. plist = *phead;
  154. if (plist == NULL) {
  155. *phead = NULL;
  156. } else {
  157. if (plist == pdelete) {
  158. *phead = plist->pnext;
  159. pdelete->pnext = NULL;
  160. } else {
  161. while (plist != NULL) {
  162. if (plist->pnext == pdelete) {
  163. plist->pnext = pdelete->pnext;
  164. pdelete->pnext = NULL;
  165. }
  166. plist = plist->pnext;
  167. }
  168. }
  169. }
  170. }
  171. /******************************************************************************
  172. * FunctionName : add_msg_type
  173. * Description : add TYPE option of DHCP message
  174. * Parameters : optptr -- the addr of DHCP message option
  175. * Returns : the addr of DHCP message option
  176. *******************************************************************************/
  177. static u8_t *add_msg_type(u8_t *optptr, u8_t type)
  178. {
  179. *optptr++ = DHCP_OPTION_MSG_TYPE;
  180. *optptr++ = 1;
  181. *optptr++ = type;
  182. return optptr;
  183. }
  184. /******************************************************************************
  185. * FunctionName : add_offer_options
  186. * Description : add OFFER option of DHCP message
  187. * Parameters : optptr -- the addr of DHCP message option
  188. * Returns : the addr of DHCP message option
  189. *******************************************************************************/
  190. static u8_t *add_offer_options(u8_t *optptr)
  191. {
  192. ip4_addr_t ipadd;
  193. ipadd.addr = *((u32_t *) &server_address);
  194. #ifdef USE_CLASS_B_NET
  195. *optptr++ = DHCP_OPTION_SUBNET_MASK;
  196. *optptr++ = 4; //length
  197. *optptr++ = 255;
  198. *optptr++ = 240;
  199. *optptr++ = 0;
  200. *optptr++ = 0;
  201. #else
  202. *optptr++ = DHCP_OPTION_SUBNET_MASK;
  203. *optptr++ = 4;
  204. *optptr++ = 255;
  205. *optptr++ = 255;
  206. *optptr++ = 255;
  207. *optptr++ = 0;
  208. #endif
  209. *optptr++ = DHCP_OPTION_LEASE_TIME;
  210. *optptr++ = 4;
  211. *optptr++ = ((dhcps_lease_time * 60) >> 24) & 0xFF;
  212. *optptr++ = ((dhcps_lease_time * 60) >> 16) & 0xFF;
  213. *optptr++ = ((dhcps_lease_time * 60) >> 8) & 0xFF;
  214. *optptr++ = ((dhcps_lease_time * 60) >> 0) & 0xFF;
  215. *optptr++ = DHCP_OPTION_SERVER_ID;
  216. *optptr++ = 4;
  217. *optptr++ = ip4_addr1(&ipadd);
  218. *optptr++ = ip4_addr2(&ipadd);
  219. *optptr++ = ip4_addr3(&ipadd);
  220. *optptr++ = ip4_addr4(&ipadd);
  221. if (dhcps_router_enabled(dhcps_offer)) {
  222. tcpip_adapter_ip_info_t if_ip;
  223. //bzero(&if_ip, sizeof(struct ip_info));
  224. memset(&if_ip , 0x00, sizeof(tcpip_adapter_ip_info_t));
  225. tcpip_adapter_get_ip_info(ESP_IF_WIFI_AP, &if_ip);
  226. if (!ip4_addr_isany_val(if_ip.gw)) {
  227. *optptr++ = DHCP_OPTION_ROUTER;
  228. *optptr++ = 4;
  229. *optptr++ = ip4_addr1(&if_ip.gw);
  230. *optptr++ = ip4_addr2(&if_ip.gw);
  231. *optptr++ = ip4_addr3(&if_ip.gw);
  232. *optptr++ = ip4_addr4(&if_ip.gw);
  233. }
  234. }
  235. #ifdef USE_DNS
  236. *optptr++ = DHCP_OPTION_DNS_SERVER;
  237. *optptr++ = 4;
  238. *optptr++ = ip4_addr1(&ipadd);
  239. *optptr++ = ip4_addr2(&ipadd);
  240. *optptr++ = ip4_addr3(&ipadd);
  241. *optptr++ = ip4_addr4(&ipadd);
  242. #endif
  243. #ifdef CLASS_B_NET
  244. *optptr++ = DHCP_OPTION_BROADCAST_ADDRESS;
  245. *optptr++ = 4;
  246. *optptr++ = ip4_addr1(&ipadd);
  247. *optptr++ = 255;
  248. *optptr++ = 255;
  249. *optptr++ = 255;
  250. #else
  251. *optptr++ = DHCP_OPTION_BROADCAST_ADDRESS;
  252. *optptr++ = 4;
  253. *optptr++ = ip4_addr1(&ipadd);
  254. *optptr++ = ip4_addr2(&ipadd);
  255. *optptr++ = ip4_addr3(&ipadd);
  256. *optptr++ = 255;
  257. #endif
  258. *optptr++ = DHCP_OPTION_INTERFACE_MTU;
  259. *optptr++ = 2;
  260. #ifdef CLASS_B_NET
  261. *optptr++ = 0x05;
  262. *optptr++ = 0xdc;
  263. #else
  264. *optptr++ = 0x02;
  265. *optptr++ = 0x40;
  266. #endif
  267. *optptr++ = DHCP_OPTION_PERFORM_ROUTER_DISCOVERY;
  268. *optptr++ = 1;
  269. *optptr++ = 0x00;
  270. *optptr++ = 43;
  271. *optptr++ = 6;
  272. *optptr++ = 0x01;
  273. *optptr++ = 4;
  274. *optptr++ = 0x00;
  275. *optptr++ = 0x00;
  276. *optptr++ = 0x00;
  277. *optptr++ = 0x02;
  278. return optptr;
  279. }
  280. /******************************************************************************
  281. * FunctionName : add_end
  282. * Description : add end option of DHCP message
  283. * Parameters : optptr -- the addr of DHCP message option
  284. * Returns : the addr of DHCP message option
  285. *******************************************************************************/
  286. static u8_t *add_end(u8_t *optptr)
  287. {
  288. *optptr++ = DHCP_OPTION_END;
  289. return optptr;
  290. }
  291. /******************************************************************************
  292. * FunctionName : create_msg
  293. * Description : create response message
  294. * Parameters : m -- DHCP message info
  295. * Returns : none
  296. *******************************************************************************/
  297. static void create_msg(struct dhcps_msg *m)
  298. {
  299. ip4_addr_t client;
  300. client.addr = *((uint32_t *) &client_address);
  301. m->op = DHCP_REPLY;
  302. m->htype = DHCP_HTYPE_ETHERNET;
  303. m->hlen = 6;
  304. m->hops = 0;
  305. // os_memcpy((char *) xid, (char *) m->xid, sizeof(m->xid));
  306. m->secs = 0;
  307. m->flags = htons(BOOTP_BROADCAST);
  308. memcpy((char *) m->yiaddr, (char *) &client.addr, sizeof(m->yiaddr));
  309. memset((char *) m->ciaddr, 0, sizeof(m->ciaddr));
  310. memset((char *) m->siaddr, 0, sizeof(m->siaddr));
  311. memset((char *) m->giaddr, 0, sizeof(m->giaddr));
  312. memset((char *) m->sname, 0, sizeof(m->sname));
  313. memset((char *) m->file, 0, sizeof(m->file));
  314. memset((char *) m->options, 0, sizeof(m->options));
  315. u32_t magic_cookie_temp = magic_cookie;
  316. memcpy((char *) m->options, &magic_cookie_temp, sizeof(magic_cookie_temp));
  317. }
  318. /******************************************************************************
  319. * FunctionName : send_offer
  320. * Description : DHCP message OFFER Response
  321. * Parameters : m -- DHCP message info
  322. * Returns : none
  323. *******************************************************************************/
  324. static void send_offer(struct dhcps_msg *m)
  325. {
  326. u8_t *end;
  327. struct pbuf *p, *q;
  328. u8_t *data;
  329. u16_t cnt = 0;
  330. u16_t i;
  331. err_t SendOffer_err_t;
  332. create_msg(m);
  333. end = add_msg_type(&m->options[4], DHCPOFFER);
  334. end = add_offer_options(end);
  335. end = add_end(end);
  336. p = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct dhcps_msg), PBUF_RAM);
  337. #if DHCPS_DEBUG
  338. DHCPS_LOG("udhcp: send_offer>>p->ref = %d\n", p->ref);
  339. #endif
  340. if (p != NULL) {
  341. #if DHCPS_DEBUG
  342. DHCPS_LOG("dhcps: send_offer>>pbuf_alloc succeed\n");
  343. DHCPS_LOG("dhcps: send_offer>>p->tot_len = %d\n", p->tot_len);
  344. DHCPS_LOG("dhcps: send_offer>>p->len = %d\n", p->len);
  345. #endif
  346. q = p;
  347. while (q != NULL) {
  348. data = (u8_t *)q->payload;
  349. for (i = 0; i < q->len; i++) {
  350. data[i] = ((u8_t *) m)[cnt++];
  351. #if DHCPS_DEBUG
  352. DHCPS_LOG("%02x ", data[i]);
  353. if ((i + 1) % 16 == 0) {
  354. DHCPS_LOG("\n");
  355. }
  356. #endif
  357. }
  358. q = q->next;
  359. }
  360. } else {
  361. #if DHCPS_DEBUG
  362. DHCPS_LOG("dhcps: send_offer>>pbuf_alloc failed\n");
  363. #endif
  364. return;
  365. }
  366. ip_addr_t ip_temp = IPADDR4_INIT(0x0);
  367. ip4_addr_set(ip_2_ip4(&ip_temp), &broadcast_dhcps);
  368. SendOffer_err_t = udp_sendto(pcb_dhcps, p, &ip_temp, DHCPS_CLIENT_PORT);
  369. #if DHCPS_DEBUG
  370. DHCPS_LOG("dhcps: send_offer>>udp_sendto result %x\n", SendOffer_err_t);
  371. #endif
  372. if (p->ref != 0) {
  373. #if DHCPS_DEBUG
  374. DHCPS_LOG("udhcp: send_offer>>free pbuf\n");
  375. #endif
  376. pbuf_free(p);
  377. }
  378. }
  379. /******************************************************************************
  380. * FunctionName : send_nak
  381. * Description : DHCP message NACK Response
  382. * Parameters : m -- DHCP message info
  383. * Returns : none
  384. *******************************************************************************/
  385. static void send_nak(struct dhcps_msg *m)
  386. {
  387. u8_t *end;
  388. struct pbuf *p, *q;
  389. u8_t *data;
  390. u16_t cnt = 0;
  391. u16_t i;
  392. err_t SendNak_err_t;
  393. create_msg(m);
  394. end = add_msg_type(&m->options[4], DHCPNAK);
  395. end = add_end(end);
  396. p = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct dhcps_msg), PBUF_RAM);
  397. #if DHCPS_DEBUG
  398. DHCPS_LOG("udhcp: send_nak>>p->ref = %d\n", p->ref);
  399. #endif
  400. if (p != NULL) {
  401. #if DHCPS_DEBUG
  402. DHCPS_LOG("dhcps: send_nak>>pbuf_alloc succeed\n");
  403. DHCPS_LOG("dhcps: send_nak>>p->tot_len = %d\n", p->tot_len);
  404. DHCPS_LOG("dhcps: send_nak>>p->len = %d\n", p->len);
  405. #endif
  406. q = p;
  407. while (q != NULL) {
  408. data = (u8_t *)q->payload;
  409. for (i = 0; i < q->len; i++) {
  410. data[i] = ((u8_t *) m)[cnt++];
  411. #if DHCPS_DEBUG
  412. DHCPS_LOG("%02x ", data[i]);
  413. if ((i + 1) % 16 == 0) {
  414. DHCPS_LOG("\n");
  415. }
  416. #endif
  417. }
  418. q = q->next;
  419. }
  420. } else {
  421. #if DHCPS_DEBUG
  422. DHCPS_LOG("dhcps: send_nak>>pbuf_alloc failed\n");
  423. #endif
  424. return;
  425. }
  426. ip_addr_t ip_temp = IPADDR4_INIT(0x0);
  427. ip4_addr_set(ip_2_ip4(&ip_temp), &broadcast_dhcps);
  428. SendNak_err_t = udp_sendto(pcb_dhcps, p, &ip_temp, DHCPS_CLIENT_PORT);
  429. #if DHCPS_DEBUG
  430. DHCPS_LOG("dhcps: send_nak>>udp_sendto result %x\n", SendNak_err_t);
  431. #endif
  432. if (p->ref != 0) {
  433. #if DHCPS_DEBUG
  434. DHCPS_LOG("udhcp: send_nak>>free pbuf\n");
  435. #endif
  436. pbuf_free(p);
  437. }
  438. }
  439. /******************************************************************************
  440. * FunctionName : send_ack
  441. * Description : DHCP message ACK Response
  442. * Parameters : m -- DHCP message info
  443. * Returns : none
  444. *******************************************************************************/
  445. static void send_ack(struct dhcps_msg *m)
  446. {
  447. u8_t *end;
  448. struct pbuf *p, *q;
  449. u8_t *data;
  450. u16_t cnt = 0;
  451. u16_t i;
  452. err_t SendAck_err_t;
  453. create_msg(m);
  454. end = add_msg_type(&m->options[4], DHCPACK);
  455. end = add_offer_options(end);
  456. end = add_end(end);
  457. p = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct dhcps_msg), PBUF_RAM);
  458. #if DHCPS_DEBUG
  459. DHCPS_LOG("udhcp: send_ack>>p->ref = %d\n", p->ref);
  460. #endif
  461. if (p != NULL) {
  462. #if DHCPS_DEBUG
  463. DHCPS_LOG("dhcps: send_ack>>pbuf_alloc succeed\n");
  464. DHCPS_LOG("dhcps: send_ack>>p->tot_len = %d\n", p->tot_len);
  465. DHCPS_LOG("dhcps: send_ack>>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_ack>>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), &broadcast_dhcps);
  489. SendAck_err_t = udp_sendto(pcb_dhcps, p, &ip_temp, DHCPS_CLIENT_PORT);
  490. #if DHCPS_DEBUG
  491. DHCPS_LOG("dhcps: send_ack>>udp_sendto result %x\n", SendAck_err_t);
  492. #endif
  493. if (p->ref != 0) {
  494. #if DHCPS_DEBUG
  495. DHCPS_LOG("udhcp: send_ack>>free pbuf\n");
  496. #endif
  497. pbuf_free(p);
  498. }
  499. }
  500. /******************************************************************************
  501. * FunctionName : parse_options
  502. * Description : parse DHCP message options
  503. * Parameters : optptr -- DHCP message option info
  504. * len -- DHCP message option length
  505. * Returns : none
  506. *******************************************************************************/
  507. static u8_t parse_options(u8_t *optptr, s16_t len)
  508. {
  509. ip4_addr_t client;
  510. bool is_dhcp_parse_end = false;
  511. struct dhcps_state s;
  512. client.addr = *((uint32_t *) &client_address);
  513. u8_t *end = optptr + len;
  514. u16_t type = 0;
  515. s.state = DHCPS_STATE_IDLE;
  516. while (optptr < end) {
  517. #if DHCPS_DEBUG
  518. DHCPS_LOG("dhcps: (s16_t)*optptr = %d\n", (s16_t)*optptr);
  519. #endif
  520. switch ((s16_t) *optptr) {
  521. case DHCP_OPTION_MSG_TYPE: //53
  522. type = *(optptr + 2);
  523. break;
  524. case DHCP_OPTION_REQ_IPADDR://50
  525. if (memcmp((char *) &client.addr, (char *) optptr + 2, 4) == 0) {
  526. #if DHCPS_DEBUG
  527. DHCPS_LOG("dhcps: DHCP_OPTION_REQ_IPADDR = 0 ok\n");
  528. #endif
  529. s.state = DHCPS_STATE_ACK;
  530. } else {
  531. #if DHCPS_DEBUG
  532. DHCPS_LOG("dhcps: DHCP_OPTION_REQ_IPADDR != 0 err\n");
  533. #endif
  534. s.state = DHCPS_STATE_NAK;
  535. }
  536. break;
  537. case DHCP_OPTION_END: {
  538. is_dhcp_parse_end = true;
  539. }
  540. break;
  541. }
  542. if (is_dhcp_parse_end) {
  543. break;
  544. }
  545. optptr += optptr[1] + 2;
  546. }
  547. switch (type) {
  548. case DHCPDISCOVER://1
  549. s.state = DHCPS_STATE_OFFER;
  550. #if DHCPS_DEBUG
  551. DHCPS_LOG("dhcps: DHCPD_STATE_OFFER\n");
  552. #endif
  553. break;
  554. case DHCPREQUEST://3
  555. if (!(s.state == DHCPS_STATE_ACK || s.state == DHCPS_STATE_NAK)) {
  556. if (renew == true) {
  557. s.state = DHCPS_STATE_ACK;
  558. } else {
  559. s.state = DHCPS_STATE_NAK;
  560. }
  561. #if DHCPS_DEBUG
  562. DHCPS_LOG("dhcps: DHCPD_STATE_NAK\n");
  563. #endif
  564. }
  565. break;
  566. case DHCPDECLINE://4
  567. s.state = DHCPS_STATE_IDLE;
  568. #if DHCPS_DEBUG
  569. DHCPS_LOG("dhcps: DHCPD_STATE_IDLE\n");
  570. #endif
  571. break;
  572. case DHCPRELEASE://7
  573. s.state = DHCPS_STATE_RELEASE;
  574. #if DHCPS_DEBUG
  575. DHCPS_LOG("dhcps: DHCPD_STATE_IDLE\n");
  576. #endif
  577. break;
  578. }
  579. #if DHCPS_DEBUG
  580. DHCPS_LOG("dhcps: return s.state = %d\n", s.state);
  581. #endif
  582. return s.state;
  583. }
  584. /******************************************************************************
  585. * FunctionName : parse_msg
  586. * Description : parse DHCP message from netif
  587. * Parameters : m -- DHCP message info
  588. * len -- DHCP message length
  589. * Returns : DHCP message type
  590. *******************************************************************************/
  591. static s16_t parse_msg(struct dhcps_msg *m, u16_t len)
  592. {
  593. if (memcmp((char *)m->options, &magic_cookie, sizeof(magic_cookie)) == 0) {
  594. #if DHCPS_DEBUG
  595. DHCPS_LOG("dhcps: len = %d\n", len);
  596. #endif
  597. ip4_addr_t addr_tmp;
  598. struct dhcps_pool *pdhcps_pool = NULL;
  599. list_node *pnode = NULL;
  600. list_node *pback_node = NULL;
  601. ip4_addr_t first_address;
  602. bool flag = false;
  603. first_address.addr = dhcps_poll.start_ip.addr;
  604. client_address.addr = client_address_plus.addr;
  605. renew = false;
  606. if (plist != NULL) {
  607. for (pback_node = plist; pback_node != NULL; pback_node = pback_node->pnext) {
  608. pdhcps_pool = pback_node->pnode;
  609. if (memcmp(pdhcps_pool->mac, m->chaddr, sizeof(pdhcps_pool->mac)) == 0) {
  610. if (memcmp(&pdhcps_pool->ip.addr, m->ciaddr, sizeof(pdhcps_pool->ip.addr)) == 0) {
  611. renew = true;
  612. }
  613. client_address.addr = pdhcps_pool->ip.addr;
  614. pdhcps_pool->lease_timer = dhcps_lease_time;
  615. pnode = pback_node;
  616. goto POOL_CHECK;
  617. } else if (pdhcps_pool->ip.addr == client_address_plus.addr) {
  618. addr_tmp.addr = htonl(client_address_plus.addr);
  619. addr_tmp.addr++;
  620. client_address_plus.addr = htonl(addr_tmp.addr);
  621. client_address.addr = client_address_plus.addr;
  622. }
  623. if (flag == false) { // search the fisrt unused ip
  624. if (first_address.addr < pdhcps_pool->ip.addr) {
  625. flag = true;
  626. } else {
  627. addr_tmp.addr = htonl(first_address.addr);
  628. addr_tmp.addr++;
  629. first_address.addr = htonl(addr_tmp.addr);
  630. }
  631. }
  632. }
  633. } else {
  634. client_address.addr = dhcps_poll.start_ip.addr;
  635. }
  636. if (client_address_plus.addr > dhcps_poll.end_ip.addr) {
  637. client_address.addr = first_address.addr;
  638. }
  639. if (client_address.addr > dhcps_poll.end_ip.addr) {
  640. client_address_plus.addr = dhcps_poll.start_ip.addr;
  641. pdhcps_pool = NULL;
  642. pnode = NULL;
  643. } else {
  644. pdhcps_pool = (struct dhcps_pool *)malloc(sizeof(struct dhcps_pool));
  645. memset(pdhcps_pool , 0x00 , sizeof(struct dhcps_pool));
  646. pdhcps_pool->ip.addr = client_address.addr;
  647. memcpy(pdhcps_pool->mac, m->chaddr, sizeof(pdhcps_pool->mac));
  648. pdhcps_pool->lease_timer = dhcps_lease_time;
  649. pnode = (list_node *)malloc(sizeof(list_node));
  650. memset(pnode , 0x00 , sizeof(list_node));
  651. pnode->pnode = pdhcps_pool;
  652. pnode->pnext = NULL;
  653. node_insert_to_list(&plist, pnode);
  654. if (client_address.addr == dhcps_poll.end_ip.addr) {
  655. client_address_plus.addr = dhcps_poll.start_ip.addr;
  656. } else {
  657. addr_tmp.addr = htonl(client_address.addr);
  658. addr_tmp.addr++;
  659. client_address_plus.addr = htonl(addr_tmp.addr);
  660. }
  661. }
  662. POOL_CHECK:
  663. if ((client_address.addr > dhcps_poll.end_ip.addr) || (ip4_addr_isany(&client_address))) {
  664. if (pnode != NULL) {
  665. node_remove_from_list(&plist, pnode);
  666. free(pnode);
  667. pnode = NULL;
  668. }
  669. if (pdhcps_pool != NULL) {
  670. free(pdhcps_pool);
  671. pdhcps_pool = NULL;
  672. }
  673. return 4;
  674. }
  675. s16_t ret = parse_options(&m->options[4], len);;
  676. if (ret == DHCPS_STATE_RELEASE) {
  677. if (pnode != NULL) {
  678. node_remove_from_list(&plist, pnode);
  679. free(pnode);
  680. pnode = NULL;
  681. }
  682. if (pdhcps_pool != NULL) {
  683. free(pdhcps_pool);
  684. pdhcps_pool = NULL;
  685. }
  686. memset(&client_address, 0x0, sizeof(client_address));
  687. }
  688. #if DHCPS_DEBUG
  689. DHCPS_LOG("dhcps: xid changed\n");
  690. DHCPS_LOG("dhcps: client_address.addr = %x\n", client_address.addr);
  691. #endif
  692. return ret;
  693. }
  694. return 0;
  695. }
  696. /******************************************************************************
  697. * FunctionName : handle_dhcp
  698. * Description : If an incoming DHCP message is in response to us, then trigger the state machine
  699. * Parameters : arg -- arg user supplied argument (udp_pcb.recv_arg)
  700. * pcb -- the udp_pcb which received data
  701. * p -- the packet buffer that was received
  702. * addr -- the remote IP address from which the packet was received
  703. * port -- the remote port from which the packet was received
  704. * Returns : none
  705. *******************************************************************************/
  706. static void handle_dhcp(void *arg,
  707. struct udp_pcb *pcb,
  708. struct pbuf *p,
  709. const ip_addr_t *addr,
  710. u16_t port)
  711. {
  712. struct dhcps_msg *pmsg_dhcps = NULL;
  713. s16_t tlen;
  714. u16_t i;
  715. u16_t dhcps_msg_cnt = 0;
  716. u8_t *p_dhcps_msg = NULL;
  717. u8_t *data;
  718. #if DHCPS_DEBUG
  719. DHCPS_LOG("dhcps: handle_dhcp-> receive a packet\n");
  720. #endif
  721. if (p == NULL) {
  722. return;
  723. }
  724. pmsg_dhcps = (struct dhcps_msg *)malloc(sizeof(struct dhcps_msg));
  725. memset(pmsg_dhcps , 0x00 , sizeof(struct dhcps_msg));
  726. if (NULL == pmsg_dhcps) {
  727. pbuf_free(p);
  728. return;
  729. }
  730. p_dhcps_msg = (u8_t *)pmsg_dhcps;
  731. tlen = p->tot_len;
  732. data = p->payload;
  733. #if DHCPS_DEBUG
  734. DHCPS_LOG("dhcps: handle_dhcp-> p->tot_len = %d\n", tlen);
  735. DHCPS_LOG("dhcps: handle_dhcp-> p->len = %d\n", p->len);
  736. #endif
  737. for (i = 0; i < p->len; i++) {
  738. p_dhcps_msg[dhcps_msg_cnt++] = data[i];
  739. #if DHCPS_DEBUG
  740. DHCPS_LOG("%02x ", data[i]);
  741. if ((i + 1) % 16 == 0) {
  742. DHCPS_LOG("\n");
  743. }
  744. #endif
  745. }
  746. if (p->next != NULL) {
  747. #if DHCPS_DEBUG
  748. DHCPS_LOG("dhcps: handle_dhcp-> p->next != NULL\n");
  749. DHCPS_LOG("dhcps: handle_dhcp-> p->next->tot_len = %d\n", p->next->tot_len);
  750. DHCPS_LOG("dhcps: handle_dhcp-> p->next->len = %d\n", p->next->len);
  751. #endif
  752. data = p->next->payload;
  753. for (i = 0; i < p->next->len; i++) {
  754. p_dhcps_msg[dhcps_msg_cnt++] = data[i];
  755. #if DHCPS_DEBUG
  756. DHCPS_LOG("%02x ", data[i]);
  757. if ((i + 1) % 16 == 0) {
  758. DHCPS_LOG("\n");
  759. }
  760. #endif
  761. }
  762. }
  763. #if DHCPS_DEBUG
  764. DHCPS_LOG("dhcps: handle_dhcp-> parse_msg(p)\n");
  765. #endif
  766. switch (parse_msg(pmsg_dhcps, tlen - 240)) {
  767. case DHCPS_STATE_OFFER://1
  768. #if DHCPS_DEBUG
  769. DHCPS_LOG("dhcps: handle_dhcp-> DHCPD_STATE_OFFER\n");
  770. #endif
  771. send_offer(pmsg_dhcps);
  772. break;
  773. case DHCPS_STATE_ACK://3
  774. #if DHCPS_DEBUG
  775. DHCPS_LOG("dhcps: handle_dhcp-> DHCPD_STATE_ACK\n");
  776. #endif
  777. send_ack(pmsg_dhcps);
  778. break;
  779. case DHCPS_STATE_NAK://4
  780. #if DHCPS_DEBUG
  781. DHCPS_LOG("dhcps: handle_dhcp-> DHCPD_STATE_NAK\n");
  782. #endif
  783. send_nak(pmsg_dhcps);
  784. break;
  785. default :
  786. break;
  787. }
  788. #if DHCPS_DEBUG
  789. DHCPS_LOG("dhcps: handle_dhcp-> pbuf_free(p)\n");
  790. #endif
  791. pbuf_free(p);
  792. free(pmsg_dhcps);
  793. pmsg_dhcps = NULL;
  794. }
  795. /******************************************************************************
  796. * FunctionName : dhcps_poll_set
  797. * Description : set ip poll from start to end for station
  798. * Parameters : ip -- The current ip addr
  799. * Returns : none
  800. *******************************************************************************/
  801. static void dhcps_poll_set(u32_t ip)
  802. {
  803. u32_t softap_ip = 0, local_ip = 0;
  804. u32_t start_ip = 0;
  805. u32_t end_ip = 0;
  806. if (dhcps_poll.enable == true) {
  807. softap_ip = htonl(ip);
  808. start_ip = htonl(dhcps_poll.start_ip.addr);
  809. end_ip = htonl(dhcps_poll.end_ip.addr);
  810. /*config ip information can't contain local ip*/
  811. if ((start_ip <= softap_ip) && (softap_ip <= end_ip)) {
  812. dhcps_poll.enable = false;
  813. } else {
  814. /*config ip information must be in the same segment as the local ip*/
  815. softap_ip >>= 8;
  816. if (((start_ip >> 8 != softap_ip) || (end_ip >> 8 != softap_ip))
  817. || (end_ip - start_ip > DHCPS_MAX_LEASE)) {
  818. dhcps_poll.enable = false;
  819. }
  820. }
  821. }
  822. if (dhcps_poll.enable == false) {
  823. local_ip = softap_ip = htonl(ip);
  824. softap_ip &= 0xFFFFFF00;
  825. local_ip &= 0xFF;
  826. if (local_ip >= 0x80) {
  827. local_ip -= DHCPS_MAX_LEASE;
  828. } else {
  829. local_ip ++;
  830. }
  831. bzero(&dhcps_poll, sizeof(dhcps_poll));
  832. dhcps_poll.start_ip.addr = softap_ip | local_ip;
  833. dhcps_poll.end_ip.addr = softap_ip | (local_ip + DHCPS_MAX_LEASE - 1);
  834. dhcps_poll.start_ip.addr = htonl(dhcps_poll.start_ip.addr);
  835. dhcps_poll.end_ip.addr = htonl(dhcps_poll.end_ip.addr);
  836. }
  837. }
  838. /******************************************************************************
  839. * FunctionName : dhcps_start
  840. * Description : start dhcp server function
  841. * Parameters : netif -- The current netif addr
  842. * : info -- The current ip info
  843. * Returns : none
  844. *******************************************************************************/
  845. void dhcps_start(struct netif *netif, ip4_addr_t ip)
  846. {
  847. struct netif *apnetif = netif;
  848. if (apnetif->dhcps_pcb != NULL) {
  849. udp_remove(apnetif->dhcps_pcb);
  850. }
  851. pcb_dhcps = udp_new();
  852. if (pcb_dhcps == NULL || ip4_addr_isany_val(ip)) {
  853. printf("dhcps_start(): could not obtain pcb\n");
  854. }
  855. apnetif->dhcps_pcb = pcb_dhcps;
  856. IP4_ADDR(&broadcast_dhcps, 255, 255, 255, 255);
  857. server_address.addr = ip.addr;
  858. dhcps_poll_set(server_address.addr);
  859. client_address_plus.addr = dhcps_poll.start_ip.addr;
  860. udp_bind(pcb_dhcps, IP_ADDR_ANY, DHCPS_SERVER_PORT);
  861. udp_recv(pcb_dhcps, handle_dhcp, NULL);
  862. #if DHCPS_DEBUG
  863. DHCPS_LOG("dhcps:dhcps_start->udp_recv function Set a receive callback handle_dhcp for UDP_PCB pcb_dhcps\n");
  864. #endif
  865. }
  866. /******************************************************************************
  867. * FunctionName : dhcps_stop
  868. * Description : stop dhcp server function
  869. * Parameters : netif -- The current netif addr
  870. * Returns : none
  871. *******************************************************************************/
  872. void dhcps_stop(struct netif *netif)
  873. {
  874. struct netif *apnetif = netif;
  875. if (apnetif == NULL) {
  876. printf("dhcps_stop: apnetif == NULL\n");
  877. return;
  878. }
  879. if (apnetif->dhcps_pcb != NULL) {
  880. udp_disconnect(apnetif->dhcps_pcb);
  881. udp_remove(apnetif->dhcps_pcb);
  882. apnetif->dhcps_pcb = NULL;
  883. }
  884. list_node *pnode = NULL;
  885. list_node *pback_node = NULL;
  886. pnode = plist;
  887. while (pnode != NULL) {
  888. pback_node = pnode;
  889. pnode = pback_node->pnext;
  890. node_remove_from_list(&plist, pback_node);
  891. free(pback_node->pnode);
  892. pback_node->pnode = NULL;
  893. free(pback_node);
  894. pback_node = NULL;
  895. }
  896. }
  897. /******************************************************************************
  898. * FunctionName : kill_oldest_dhcps_pool
  899. * Description : remove the oldest node from list
  900. * Parameters : none
  901. * Returns : none
  902. *******************************************************************************/
  903. static void kill_oldest_dhcps_pool(void)
  904. {
  905. list_node *pre = NULL, *p = NULL;
  906. list_node *minpre = NULL, *minp = NULL;
  907. struct dhcps_pool *pdhcps_pool = NULL, *pmin_pool = NULL;
  908. pre = plist;
  909. p = pre->pnext;
  910. minpre = pre;
  911. minp = p;
  912. while (p != NULL) {
  913. pdhcps_pool = p->pnode;
  914. pmin_pool = minp->pnode;
  915. if (pdhcps_pool->lease_timer < pmin_pool->lease_timer) {
  916. minp = p;
  917. minpre = pre;
  918. }
  919. pre = p;
  920. p = p->pnext;
  921. }
  922. minpre->pnext = minp->pnext;
  923. free(minp->pnode);
  924. minp->pnode = NULL;
  925. free(minp);
  926. minp = NULL;
  927. }
  928. /******************************************************************************
  929. * FunctionName : dhcps_coarse_tmr
  930. * Description : the lease time count
  931. * Parameters : none
  932. * Returns : none
  933. *******************************************************************************/
  934. void dhcps_coarse_tmr(void)
  935. {
  936. u8_t num_dhcps_pool = 0;
  937. list_node *pback_node = NULL;
  938. list_node *pnode = NULL;
  939. struct dhcps_pool *pdhcps_pool = NULL;
  940. pnode = plist;
  941. while (pnode != NULL) {
  942. pdhcps_pool = pnode->pnode;
  943. pdhcps_pool->lease_timer --;
  944. if (pdhcps_pool->lease_timer == 0) {
  945. pback_node = pnode;
  946. pnode = pback_node->pnext;
  947. node_remove_from_list(&plist, pback_node);
  948. free(pback_node->pnode);
  949. pback_node->pnode = NULL;
  950. free(pback_node);
  951. pback_node = NULL;
  952. } else {
  953. pnode = pnode ->pnext;
  954. num_dhcps_pool ++;
  955. }
  956. }
  957. if (num_dhcps_pool >= MAX_STATION_NUM) {
  958. kill_oldest_dhcps_pool();
  959. }
  960. }
  961. /******************************************************************************
  962. * FunctionName : dhcp_search_ip_on_mac
  963. * Description : Search ip address based on mac address
  964. * Parameters : mac -- The MAC addr
  965. * ip -- The IP info
  966. * Returns : true or false
  967. *******************************************************************************/
  968. bool dhcp_search_ip_on_mac(u8_t *mac, ip4_addr_t *ip)
  969. {
  970. struct dhcps_pool *pdhcps_pool = NULL;
  971. list_node *pback_node = NULL;
  972. bool ret = false;
  973. for (pback_node = plist; pback_node != NULL; pback_node = pback_node->pnext) {
  974. pdhcps_pool = pback_node->pnode;
  975. if (memcmp(pdhcps_pool->mac, mac, sizeof(pdhcps_pool->mac)) == 0) {
  976. memcpy(&ip->addr, &pdhcps_pool->ip.addr, sizeof(pdhcps_pool->ip.addr));
  977. ret = true;
  978. break;
  979. }
  980. }
  981. return ret;
  982. }
  983. #endif