FreeRTOS_DHCP_Server.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666
  1. /*
  2. * porting from lwip
  3. */
  4. #include <string.h>
  5. #include <stdint.h>
  6. #include <stdio.h>
  7. #include <FreeRTOS.h>
  8. #include <task.h>
  9. #include "FreeRTOS_IP.h"
  10. #include "FreeRTOS_IP_Private.h"
  11. #include "FreeRTOS_Sockets.h"
  12. #include "FreeRTOS_DHCP_Server.h"
  13. #include "NetworkBufferManagement.h"
  14. #if (DHCP_DEBUG == LWIP_DBG_ON)
  15. #define debug(s, ...) printf("%s: " s "\n", "DHCP", ## __VA_ARGS__)
  16. #else
  17. #define debug(s, ...)
  18. #endif
  19. /* Grow the size of the lwip dhcp_msg struct's options field, as LWIP
  20. defaults to a 68 octet options field for its DHCP client, and most
  21. full-sized clients send us more than this. */
  22. #define DHCP_OPTIONS_LEN 312
  23. #define NETIF_MAX_HWADDR_LEN 6U
  24. #define DHCP_FILE_LEN 128U
  25. #define DHCP_SNAME_LEN 64U
  26. #define DHCP_CHADDR_LEN 16U
  27. #define LWIP_IANA_HWTYPE_ETHERNET 1
  28. /* DHCP op codes */
  29. #define DHCP_BOOTREQUEST 1
  30. #define DHCP_BOOTREPLY 2
  31. /* DHCP message types */
  32. #define DHCP_DISCOVER 1
  33. #define DHCP_OFFER 2
  34. #define DHCP_REQUEST 3
  35. #define DHCP_DECLINE 4
  36. #define DHCP_ACK 5
  37. #define DHCP_NAK 6
  38. #define DHCP_RELEASE 7
  39. #define DHCP_INFORM 8
  40. #define DHCP_MAGIC_COOKIE 0x63825363UL
  41. /* This is a list of options for BOOTP and DHCP, see RFC 2132 for descriptions */
  42. /* BootP options */
  43. #define DHCP_OPTION_PAD 0
  44. #define DHCP_OPTION_SUBNET_MASK 1 /* RFC 2132 3.3 */
  45. #define DHCP_OPTION_ROUTER 3
  46. #define DHCP_OPTION_DNS_SERVER 6
  47. #define DHCP_OPTION_HOSTNAME 12
  48. #define DHCP_OPTION_IP_TTL 23
  49. #define DHCP_OPTION_MTU 26
  50. #define DHCP_OPTION_BROADCAST 28
  51. #define DHCP_OPTION_TCP_TTL 37
  52. #define DHCP_OPTION_NTP 42
  53. #define DHCP_OPTION_END 255
  54. /* DHCP options */
  55. #define DHCP_OPTION_REQUESTED_IP 50 /* RFC 2132 9.1, requested IP address */
  56. #define DHCP_OPTION_LEASE_TIME 51 /* RFC 2132 9.2, time in seconds, in 4 bytes */
  57. #define DHCP_OPTION_OVERLOAD 52 /* RFC2132 9.3, use file and/or sname field for options */
  58. #define DHCP_OPTION_MESSAGE_TYPE 53 /* RFC 2132 9.6, important for DHCP */
  59. #define DHCP_OPTION_MESSAGE_TYPE_LEN 1
  60. #define DHCP_OPTION_SERVER_ID 54 /* RFC 2132 9.7, server IP address */
  61. #define DHCP_OPTION_PARAMETER_REQUEST_LIST 55 /* RFC 2132 9.8, requested option types */
  62. #define DHCP_OPTION_MAX_MSG_SIZE 57 /* RFC 2132 9.10, message size accepted >= 576 */
  63. #define DHCP_OPTION_MAX_MSG_SIZE_LEN 2
  64. #define DHCP_OPTION_T1 58 /* T1 renewal time */
  65. #define DHCP_OPTION_T2 59 /* T2 rebinding time */
  66. #define DHCP_OPTION_US 60
  67. #define DHCP_OPTION_CLIENT_ID 61
  68. #define DHCP_OPTION_TFTP_SERVERNAME 66
  69. #define DHCP_OPTION_BOOTFILE 67
  70. /* possible combinations of overloading the file and sname fields with options */
  71. #define DHCP_OVERLOAD_NONE 0
  72. #define DHCP_OVERLOAD_FILE 1
  73. #define DHCP_OVERLOAD_SNAME 2
  74. #define DHCP_OVERLOAD_SNAME_FILE 3
  75. #define IPADDR_ANY ((uint32_t)0x00000000UL)
  76. #define ip4_addr_get_byte(ipaddr, idx) (((const uint8_t*)(&(ipaddr)->addr))[idx])
  77. #define ip4_addr1(ipaddr) ip4_addr_get_byte(ipaddr, 0)
  78. #define ip4_addr2(ipaddr) ip4_addr_get_byte(ipaddr, 1)
  79. #define ip4_addr3(ipaddr) ip4_addr_get_byte(ipaddr, 2)
  80. #define ip4_addr4(ipaddr) ip4_addr_get_byte(ipaddr, 3)
  81. #define ip4_addr_copy(dest, src) ((dest).addr = (src).addr)
  82. #define ip4_addr_set_zero(ipaddr) ((ipaddr)->addr = 0)
  83. #define ip4_addr_isany_val(addr1) ((addr1).addr == IPADDR_ANY)
  84. #define ip4_addr_cmp(addr1, addr2) ((addr1)->addr == (addr2)->addr)
  85. #define ip_addr_cmp(addr1, addr2) ip4_addr_cmp(addr1, addr2)
  86. #define swap16(A) ((((uint16_t)(A) & 0xff00) >> 8) | (((uint16_t)(A) & 0x00ff) << 8))
  87. #define swap32(A) ((((uint32_t)(A) & 0xff000000) >> 24) | \
  88. (((uint32_t)(A) & 0x00ff0000) >> 8) | \
  89. (((uint32_t)(A) & 0x0000ff00) << 8) | \
  90. (((uint32_t)(A) & 0x000000ff) << 24))
  91. #define IPADDR_BROADCAST ((uint32_t)0xffffffffUL)
  92. static union {
  93. char c[4];
  94. unsigned long l;
  95. } endian_test = {{ 'l', '?', '?', 'b' } };
  96. #define ENDIANNESS ((char)endian_test.l)
  97. uint16_t htons(uint16_t hs)
  98. {
  99. return (ENDIANNESS=='l') ? swap16(hs): hs;
  100. }
  101. uint32_t htonl(uint32_t hl)
  102. {
  103. return (ENDIANNESS=='l') ? swap32(hl): hl;
  104. }
  105. uint16_t ntohs(uint16_t ns)
  106. {
  107. return (ENDIANNESS=='l') ? swap16(ns): ns;
  108. }
  109. uint32_t ntohl(uint32_t nl)
  110. {
  111. return (ENDIANNESS=='l') ? swap32(nl): nl;
  112. }
  113. #include "pack_struct_start.h"
  114. struct ip4_addr {
  115. uint32_t addr;
  116. };
  117. #include "pack_struct_end.h"
  118. typedef struct ip4_addr ip4_addr_t;
  119. typedef ip4_addr_t ip_addr_t;
  120. #include "pack_struct_start.h"
  121. struct dhcp_msg
  122. {
  123. uint8_t op;
  124. uint8_t htype;
  125. uint8_t hlen;
  126. uint8_t hops;
  127. uint32_t xid;
  128. uint16_t secs;
  129. uint16_t flags;
  130. ip4_addr_t ciaddr;
  131. ip4_addr_t yiaddr;
  132. ip4_addr_t siaddr;
  133. ip4_addr_t giaddr;
  134. uint8_t chaddr[DHCP_CHADDR_LEN];
  135. uint8_t sname[DHCP_SNAME_LEN];
  136. uint8_t file[DHCP_FILE_LEN];
  137. uint32_t cookie;
  138. uint8_t options[DHCP_OPTIONS_LEN];
  139. };
  140. #include "pack_struct_end.h"
  141. typedef struct {
  142. uint8_t hwaddr[NETIF_MAX_HWADDR_LEN];
  143. uint8_t active;
  144. uint32_t expires;
  145. } dhcp_lease_t;
  146. typedef struct {
  147. //struct netconn *nc;
  148. Socket_t server_handle;
  149. uint8_t max_leases;
  150. ip4_addr_t first_client_addr;
  151. //struct netif *server_if;
  152. dhcp_lease_t *leases; /* length max_leases */
  153. /* Optional router */
  154. ip4_addr_t router;
  155. /* Optional DNS server */
  156. ip4_addr_t dns;
  157. } server_state_t;
  158. struct dhcp_client_ctx
  159. {
  160. int32_t tid;
  161. ListItem_t item;
  162. TimerHandle_t timer;
  163. server_state_t* state;
  164. struct dhcp_msg msg;
  165. };
  166. static TaskHandle_t dhcpserver_task_handle = NULL;
  167. static server_state_t *gState;
  168. static List_t gdhcp_client_list;
  169. static uint32_t gDefaultIp = 0;
  170. uint32_t FreeRTOS_GetIPAddressSafe( void )
  171. {
  172. uint32_t ip = FreeRTOS_GetIPAddress();
  173. if (0 == ip) {
  174. return gDefaultIp;
  175. }
  176. return ip;
  177. }
  178. /* Handlers for various kinds of incoming DHCP messages */
  179. static void handle_dhcp_discover(server_state_t* state, struct freertos_sockaddr *xaddr, struct dhcp_msg *received);
  180. static void handle_dhcp_request(server_state_t* state, struct freertos_sockaddr *xaddr, struct dhcp_msg *dhcpmsg);
  181. static void handle_dhcp_release(server_state_t* state, struct dhcp_msg *dhcpmsg);
  182. static void send_dhcp_nak(server_state_t* state, struct freertos_sockaddr *xaddr, struct dhcp_msg *dhcpmsg);
  183. static void dhcpserver_task(void *pxParameter);
  184. /* Utility functions */
  185. static uint8_t *find_dhcp_option(struct dhcp_msg *msg, uint8_t option_num, uint8_t min_length, uint8_t *length);
  186. static uint8_t *add_dhcp_option_byte(uint8_t *opt, uint8_t type, uint8_t value);
  187. static uint8_t *add_dhcp_option_bytes(uint8_t *opt, uint8_t type, void *value, uint8_t len);
  188. static dhcp_lease_t *find_lease_slot(server_state_t* state, uint8_t *hwaddr);
  189. /* Copy IP address as dotted decimal to 'dest', must be at least 16 bytes long */
  190. inline static void sprintf_ipaddr(const ip4_addr_t *addr, char *dest)
  191. {
  192. if (addr == NULL)
  193. sprintf(dest, "NULL");
  194. else
  195. sprintf(dest, "%d.%d.%d.%d", ip4_addr1(addr),
  196. ip4_addr2(addr), ip4_addr3(addr), ip4_addr4(addr));
  197. }
  198. inline static void sprintf_ipaddr1(uint32_t addr, uint8_t *dest)
  199. {
  200. ip4_addr_t tmp = {0};
  201. tmp.addr = addr;
  202. sprintf_ipaddr(&tmp, (char*)dest);
  203. }
  204. void dhcpserver_start(const uint8_t ucIPAddress[4], uint32_t first_client_addr, uint8_t max_leases)
  205. {
  206. /* Stop any existing running dhcpserver */
  207. if (dhcpserver_task_handle) {
  208. return;
  209. }
  210. gDefaultIp = (ucIPAddress[0]) | (ucIPAddress[1] << 8) | (ucIPAddress[2] << 16) | (ucIPAddress[3] << 24);
  211. printf("dhcpserver_start-->gDefaultIp:%x\r\n", gDefaultIp);
  212. vListInitialise(&gdhcp_client_list);
  213. gState = (server_state_t*)pvPortMalloc(sizeof(server_state_t));
  214. memset(gState, 0, sizeof(*gState));
  215. gState->max_leases = max_leases;
  216. gState->leases = (dhcp_lease_t *)pvPortMalloc(max_leases * sizeof(dhcp_lease_t));
  217. memset((void*)gState->leases, 0, max_leases * sizeof(dhcp_lease_t));
  218. // state->server_if is assigned once the task is running - see comment in dhcpserver_task()
  219. //ip4_addr_copy(gState->first_client_addr, *first_client_addr);
  220. gState->first_client_addr.addr = first_client_addr;
  221. /* Clear options */
  222. ip4_addr_set_zero(&gState->router);
  223. ip4_addr_set_zero(&gState->dns);
  224. xTaskCreate(dhcpserver_task, "DHCP Server", configMINIMAL_STACK_SIZE * 4, (void*)gState, 5, &dhcpserver_task_handle);
  225. }
  226. void dhcpserver_stop(void)
  227. {
  228. if (dhcpserver_task_handle) {
  229. vTaskDelete(dhcpserver_task_handle);
  230. dhcpserver_task_handle = NULL;
  231. vPortFree((void*)gState->leases);
  232. vPortFree((void*)gState);
  233. gState = NULL;
  234. }
  235. }
  236. void dhcpserver_set_router(uint32_t router)
  237. {
  238. //ip4_addr_copy(gState->router, router);
  239. gState->router.addr = router;
  240. }
  241. void dhcpserver_set_dns(uint32_t dns)
  242. {
  243. //ip4_addr_copy(gState->dns, dns);
  244. gState->dns.addr = dns;
  245. }
  246. static void dhcpserver_task(void *pxParameter)
  247. {
  248. SocketSet_t xFD_Set;
  249. BaseType_t xResult;
  250. Socket_t xSockets;
  251. struct freertos_sockaddr xAddress;
  252. uint32_t xClientLength = sizeof( struct freertos_sockaddr );
  253. int32_t lBytes;
  254. const TickType_t xRxBlockTime = 0;
  255. uint8_t rcv_buf[4096] = {0};
  256. server_state_t* state = (server_state_t*)pxParameter;
  257. uint8_t ipAddrStr[32] = {0};
  258. xFD_Set = FreeRTOS_CreateSocketSet();
  259. xSockets = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP );
  260. xAddress.sin_port = FreeRTOS_htons( 67 );
  261. FreeRTOS_bind(xSockets, &xAddress, sizeof( struct freertos_sockaddr ));
  262. FreeRTOS_setsockopt(xSockets, 0, FREERTOS_SO_RCVTIMEO, &xRxBlockTime, sizeof( xRxBlockTime ));
  263. state->server_handle = xSockets;
  264. while(1) {
  265. FreeRTOS_FD_CLR(xSockets, xFD_Set, eSELECT_READ);
  266. FreeRTOS_FD_SET( xSockets, xFD_Set, eSELECT_READ );
  267. xResult = FreeRTOS_select( xFD_Set, portMAX_DELAY );
  268. if (xResult == 0) {
  269. continue;
  270. }
  271. struct dhcp_msg received = { 0 };
  272. /* Receive a DHCP packet */
  273. if( !FreeRTOS_FD_ISSET ( xSockets, xFD_Set ) ) {
  274. }
  275. /* Read from the socket. */
  276. lBytes = FreeRTOS_recvfrom( xSockets, (void*)rcv_buf, sizeof(rcv_buf), 0, &xAddress,
  277. &xClientLength );
  278. if (lBytes <= 0)
  279. continue;
  280. if (lBytes < (sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN))
  281. continue;
  282. /* expire any leases that have passed */
  283. uint32_t now = xTaskGetTickCount();
  284. for (int i = 0; i < state->max_leases; i++) {
  285. if (state->leases[i].active) {
  286. uint32_t expires = state->leases[i].expires - now;
  287. if (expires >= 0x80000000) {
  288. state->leases[i].active = 0;
  289. }
  290. }
  291. }
  292. memcpy((void*)&received, (void*)rcv_buf, lBytes);
  293. uint8_t *message_type = find_dhcp_option(&received, DHCP_OPTION_MESSAGE_TYPE,
  294. DHCP_OPTION_MESSAGE_TYPE_LEN, NULL);
  295. if(!message_type) {
  296. debug("DHCP Server Error: No message type field found");
  297. continue;
  298. }
  299. #if (DHCP_DEBUG == LWIP_DBG_ON)
  300. sprintf_ipaddr1(xAddress.sin_addr, ipAddrStr);
  301. debug("State dump. Message type %d from %s port:%d\r\n", *message_type, ipAddrStr, xAddress.sin_port);
  302. for(int i = 0; i < state->max_leases; i++) {
  303. #if 0
  304. dhcp_lease_t *lease = &state->leases[i];
  305. debug("lease slot %d expiry %d hwaddr %02x:%02x:%02x:%02x:%02x:%02x \r\n", i, lease->expires, lease->hwaddr[0],
  306. lease->hwaddr[1], lease->hwaddr[2], lease->hwaddr[3], lease->hwaddr[4],
  307. lease->hwaddr[5]);
  308. #endif
  309. }
  310. #endif
  311. //xAddress.sin_addr = 0xffffffffUL;
  312. //xAddress.sin_port = ( uint16_t ) 68;
  313. switch(*message_type) {
  314. case DHCP_DISCOVER:
  315. printf("DHCP_DISCOVER\r\n");
  316. handle_dhcp_discover(state, &xAddress, &received);
  317. break;
  318. case DHCP_REQUEST:
  319. printf("DHCP_REQUEST\r\n");
  320. handle_dhcp_request(state, &xAddress, &received);
  321. break;
  322. case DHCP_RELEASE:
  323. printf("DHCP_RELEASE\r\n");
  324. handle_dhcp_release(state, &received);
  325. break;
  326. default:
  327. debug("DHCP Server Error: Unsupported message type %d\r\n", *message_type);
  328. break;
  329. }
  330. }
  331. }
  332. /*static void send_dhcp_msg(server_state_t* state, struct freertos_sockaddr *xaddr, struct dhcp_msg *dhcpmsg)
  333. {
  334. NetworkBufferDescriptor_t * pxNetworkBuffer;
  335. uint8_t * pucUDPPayloadBuffer = NULL;
  336. uint32_t xClientLength = sizeof( struct freertos_sockaddr );
  337. pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( sizeof( UDPPacket_t ) + sizeof(struct dhcp_msg), 0U );
  338. if( pxNetworkBuffer == NULL ) {
  339. debug("DHCP Server: malloc net buf desc err.\r\n");
  340. return;
  341. }
  342. pucUDPPayloadBuffer = &( pxNetworkBuffer->pucEthernetBuffer[ ipUDP_PAYLOAD_OFFSET_IPv4 ] );
  343. memcpy(pucUDPPayloadBuffer, (void*)dhcpmsg, sizeof(struct dhcp_msg));
  344. FreeRTOS_sendto(state->server_handle, (void*)pucUDPPayloadBuffer, sizeof(struct dhcp_msg), FREERTOS_ZERO_COPY, xaddr, xClientLength);
  345. }*/
  346. #define dhcpdTIMER_SCAN_FREQUENCY_MS pdMS_TO_TICKS( 300UL )
  347. static void handle_dhcp_discover(server_state_t* state, struct freertos_sockaddr *xaddr, struct dhcp_msg *dhcpmsg)
  348. {
  349. uint32_t xClientLength = sizeof( struct freertos_sockaddr );
  350. int32_t ret = -1;
  351. struct dhcp_client_ctx *client = NULL;
  352. if (dhcpmsg->htype != LWIP_IANA_HWTYPE_ETHERNET)
  353. return;
  354. if (dhcpmsg->hlen > NETIF_MAX_HWADDR_LEN)
  355. return;
  356. dhcp_lease_t *freelease = find_lease_slot(state, dhcpmsg->chaddr);
  357. if(!freelease) {
  358. debug("DHCP Server: All leases taken.\r\n");
  359. return; /* Nothing available, so do nothing */
  360. }
  361. /* Reuse the DISCOVER buffer for the OFFER response */
  362. dhcpmsg->op = DHCP_BOOTREPLY;
  363. dhcpmsg->htype = LWIP_IANA_HWTYPE_ETHERNET;
  364. //bzero(dhcpmsg->options, DHCP_OPTIONS_LEN);
  365. memset((void *)dhcpmsg->options, 0, sizeof(dhcpmsg->options));
  366. dhcpmsg->yiaddr.addr = FreeRTOS_htonl(FreeRTOS_ntohl(state->first_client_addr.addr) + (freelease - state->leases));
  367. //dhcpmsg->yiaddr.addr = ((state->first_client_addr.addr) + (freelease - state->leases));
  368. uint8_t *opt = (uint8_t *)&dhcpmsg->options;
  369. opt = add_dhcp_option_byte(opt, DHCP_OPTION_MESSAGE_TYPE, DHCP_OFFER);
  370. uint32_t ser_addr = FreeRTOS_GetIPAddressSafe();
  371. opt = add_dhcp_option_bytes(opt, DHCP_OPTION_SERVER_ID, &ser_addr, 4);
  372. uint32_t ser_netmask = FreeRTOS_GetNetmask();
  373. opt = add_dhcp_option_bytes(opt, DHCP_OPTION_SUBNET_MASK, &ser_netmask, 4);//
  374. uint32_t ser_broadcast = FreeRTOS_GetIPAddressSafe();
  375. uint8_t* tmp_ptr_addr = (uint8_t*)&ser_broadcast;
  376. *(tmp_ptr_addr + 3) = 0xff;
  377. opt = add_dhcp_option_bytes(opt, DHCP_OPTION_BROADCAST, &ser_broadcast, 4);
  378. if (1) {
  379. uint8_t addr_str[32] = {0};
  380. sprintf_ipaddr1(ser_addr, addr_str);
  381. debug("server ip:%s \r\n", addr_str);
  382. sprintf_ipaddr1(xaddr->sin_addr, addr_str);
  383. debug("##client ip:%s port:%d\r\n", addr_str, FreeRTOS_htons(xaddr->sin_port));
  384. memset(addr_str, 0, sizeof(addr_str));
  385. sprintf_ipaddr1(ser_netmask, addr_str);
  386. debug("server netmask:%s \r\n", addr_str);
  387. printf("send len:%d\r\n", sizeof(struct dhcp_msg));
  388. }
  389. //if (!ip4_addr_isany_val(state->router)) {
  390. uint8_t addr_str11[32] = {0};
  391. state->router.addr = FreeRTOS_GetGatewayAddress();
  392. sprintf_ipaddr1(state->router.addr, addr_str11);
  393. debug("router ip:%s \r\n", addr_str11);
  394. opt = add_dhcp_option_bytes(opt, DHCP_OPTION_ROUTER, &state->router, 4);
  395. //}
  396. //if (!ip4_addr_isany_val(state->dns)) {
  397. state->dns.addr = FreeRTOS_GetGatewayAddress();
  398. sprintf_ipaddr1(state->dns.addr, addr_str11);
  399. debug("dns ip:%s \r\n", addr_str11);
  400. opt = add_dhcp_option_bytes(opt, DHCP_OPTION_DNS_SERVER, &state->dns, 4);
  401. //}
  402. uint32_t expiry = htonl(DHCPSERVER_LEASE_TIME);
  403. opt = add_dhcp_option_bytes(opt, DHCP_OPTION_LEASE_TIME, &expiry, 4);
  404. opt = add_dhcp_option_bytes(opt, DHCP_OPTION_END, NULL, 0);
  405. if (0) {
  406. int i;
  407. uint8_t *tmpp = (uint8_t *)dhcpmsg;
  408. for (i = 0; i < sizeof(struct dhcp_msg); i++) {
  409. printf("%02x ", tmpp[i]);
  410. }printf("\r\n");
  411. }
  412. //xaddr->sin_addr = FreeRTOS_htonl(dhcpmsg->yiaddr.addr);
  413. xaddr->sin_addr = 0xffffffff;//
  414. xaddr->sin_port = ( uint16_t ) FreeRTOS_htons(68);
  415. if (0 && NULL != client) {
  416. memcpy((void *)&client->msg, (void *)dhcpmsg, sizeof(struct dhcp_msg));
  417. client->state = state;
  418. xTimerStart(client->timer, 0);
  419. }
  420. ret = FreeRTOS_sendto(state->server_handle, (void*)dhcpmsg, sizeof(struct dhcp_msg), 0, xaddr, xClientLength);
  421. printf("len out:%d ret:%d\r\n", sizeof(struct dhcp_msg), ret);
  422. if (ret != sizeof(struct dhcp_msg)) {
  423. printf("udhcpd ret:%d\r\n", ret);
  424. }
  425. //send_dhcp_msg(state, xaddr, dhcpmsg);
  426. }
  427. static void handle_dhcp_request(server_state_t* state, struct freertos_sockaddr *xaddr, struct dhcp_msg *dhcpmsg)
  428. {
  429. uint32_t xClientLength = sizeof( struct freertos_sockaddr );
  430. static char ipbuf[16];
  431. if (dhcpmsg->htype != LWIP_IANA_HWTYPE_ETHERNET) {
  432. debug("DHCP Server Error: htype err.\r\n");
  433. return;
  434. }
  435. if (dhcpmsg->hlen > NETIF_MAX_HWADDR_LEN) {
  436. debug("DHCP Server Error: hlen err.\r\n");
  437. return;
  438. }
  439. ip4_addr_t requested_ip;
  440. ip4_addr_t any_ip = {0};
  441. any_ip.addr = IPADDR_ANY;
  442. uint8_t *requested_ip_opt = find_dhcp_option(dhcpmsg, DHCP_OPTION_REQUESTED_IP, 4, NULL);
  443. if (requested_ip_opt) {
  444. memcpy(&requested_ip.addr, requested_ip_opt, 4);
  445. } else if (ip4_addr_cmp(&requested_ip, &any_ip)) {
  446. ip4_addr_copy(requested_ip, dhcpmsg->ciaddr);
  447. } else {
  448. debug("DHCP Server Error: No requested IP");
  449. send_dhcp_nak(state, xaddr, dhcpmsg);
  450. return;
  451. }
  452. /* Test the first 4 octets match */
  453. if (ip4_addr1(&requested_ip) != ip4_addr1(&state->first_client_addr)
  454. || ip4_addr2(&requested_ip) != ip4_addr2(&state->first_client_addr)
  455. || ip4_addr3(&requested_ip) != ip4_addr3(&state->first_client_addr)) {
  456. sprintf_ipaddr(&requested_ip, ipbuf);
  457. debug("DHCP Server Error: %s not an allowed IP\r\n", ipbuf);
  458. send_dhcp_nak(state, xaddr, dhcpmsg);
  459. return;
  460. }
  461. /* Test the last octet is in the MAXCLIENTS range */
  462. int16_t octet_offs = ip4_addr4(&requested_ip) - ip4_addr4(&state->first_client_addr);
  463. if(octet_offs < 0 || octet_offs >= state->max_leases) {
  464. debug("DHCP Server Error: Address out of range\r\n");
  465. send_dhcp_nak(state, xaddr, dhcpmsg);
  466. return;
  467. }
  468. dhcp_lease_t *requested_lease = state->leases + octet_offs;
  469. if (requested_lease->active && memcmp(requested_lease->hwaddr, dhcpmsg->chaddr,dhcpmsg->hlen))
  470. {
  471. debug("DHCP Server Error: Lease for address already taken\r\n");
  472. send_dhcp_nak(state, xaddr, dhcpmsg);
  473. return;
  474. }
  475. memcpy(requested_lease->hwaddr, dhcpmsg->chaddr, dhcpmsg->hlen);
  476. sprintf_ipaddr(&requested_ip, ipbuf);
  477. debug("DHCP lease addr %s assigned to MAC %02x:%02x:%02x:%02x:%02x:%02x\r\n", ipbuf, requested_lease->hwaddr[0],
  478. requested_lease->hwaddr[1], requested_lease->hwaddr[2], requested_lease->hwaddr[3], requested_lease->hwaddr[4],
  479. requested_lease->hwaddr[5]);
  480. uint32_t now = xTaskGetTickCount();
  481. requested_lease->expires = now + DHCPSERVER_LEASE_TIME * configTICK_RATE_HZ;
  482. requested_lease->active = 1;
  483. //sdk_wifi_softap_set_station_info(requested_lease->hwaddr, &requested_ip);
  484. /* Reuse the REQUEST message as the ACK message */
  485. dhcpmsg->op = DHCP_BOOTREPLY;
  486. memset((void *)dhcpmsg->options, 0, sizeof(dhcpmsg->options));
  487. ip4_addr_copy(dhcpmsg->yiaddr, requested_ip);
  488. uint8_t *opt = (uint8_t *)&dhcpmsg->options;
  489. opt = add_dhcp_option_byte(opt, DHCP_OPTION_MESSAGE_TYPE, DHCP_ACK);
  490. uint32_t expiry = htonl(DHCPSERVER_LEASE_TIME);
  491. opt = add_dhcp_option_bytes(opt, DHCP_OPTION_LEASE_TIME, &expiry, 4);
  492. uint32_t ser_addr = FreeRTOS_GetIPAddressSafe();
  493. opt = add_dhcp_option_bytes(opt, DHCP_OPTION_SERVER_ID, &ser_addr, 4);
  494. uint32_t ser_netmask = FreeRTOS_GetNetmask();
  495. opt = add_dhcp_option_bytes(opt, DHCP_OPTION_SUBNET_MASK, &ser_netmask, 4);
  496. //if (!ip4_addr_isany_val(state->router)) {
  497. state->router.addr = FreeRTOS_GetGatewayAddress();
  498. opt = add_dhcp_option_bytes(opt, DHCP_OPTION_ROUTER, &state->router, 4);
  499. //}
  500. //if (!ip4_addr_isany_val(state->dns)) {
  501. state->dns.addr = FreeRTOS_GetGatewayAddress();
  502. opt = add_dhcp_option_bytes(opt, DHCP_OPTION_DNS_SERVER, &state->dns, 4);
  503. //}
  504. opt = add_dhcp_option_bytes(opt, DHCP_OPTION_END, NULL, 0);
  505. xaddr->sin_addr = 0xffffffff;
  506. xaddr->sin_port = ( uint16_t ) FreeRTOS_htons(68);
  507. FreeRTOS_sendto(state->server_handle, (void*)dhcpmsg, sizeof(struct dhcp_msg), 0, xaddr, xClientLength);
  508. //send_dhcp_msg(state, xaddr, dhcpmsg);
  509. }
  510. static void handle_dhcp_release(server_state_t* state, struct dhcp_msg *dhcpmsg)
  511. {
  512. dhcp_lease_t *lease = find_lease_slot(state, dhcpmsg->chaddr);
  513. if (lease) {
  514. lease->active = 0;
  515. lease->expires = 0;
  516. }
  517. }
  518. static void send_dhcp_nak(server_state_t* state, struct freertos_sockaddr *xaddr, struct dhcp_msg *dhcpmsg)
  519. {
  520. uint32_t xClientLength = sizeof( struct freertos_sockaddr );
  521. /* Reuse 'dhcpmsg' for the NAK */
  522. dhcpmsg->op = DHCP_BOOTREPLY;
  523. memset((void *)dhcpmsg->options, 0, sizeof(dhcpmsg->options));
  524. uint8_t *opt = (uint8_t *)&dhcpmsg->options;
  525. opt = add_dhcp_option_byte(opt, DHCP_OPTION_MESSAGE_TYPE, DHCP_NAK);
  526. uint32_t ser_addr = FreeRTOS_GetIPAddressSafe();
  527. opt = add_dhcp_option_bytes(opt, DHCP_OPTION_SERVER_ID, &ser_addr, 4);
  528. opt = add_dhcp_option_bytes(opt, DHCP_OPTION_END, NULL, 0);
  529. xaddr->sin_addr = 0xffffffff;
  530. xaddr->sin_port = ( uint16_t ) FreeRTOS_htons(68);
  531. FreeRTOS_sendto(state->server_handle, (void*)dhcpmsg, sizeof(struct dhcp_msg), 0, xaddr, xClientLength);
  532. //send_dhcp_msg(state, xaddr, dhcpmsg);
  533. }
  534. static uint8_t *find_dhcp_option(struct dhcp_msg *msg, uint8_t option_num, uint8_t min_length, uint8_t *length)
  535. {
  536. uint8_t *start = (uint8_t *)&msg->options;
  537. uint8_t *msg_end = (uint8_t *)msg + sizeof(struct dhcp_msg);
  538. for (uint8_t *p = start; p < msg_end-2;) {
  539. uint8_t type = *p++;
  540. uint8_t len = *p++;
  541. if (type == DHCP_OPTION_END)
  542. return NULL;
  543. if (p+len >= msg_end)
  544. break; /* We've overrun our valid DHCP message size, or this isn't a valid option */
  545. if (type == option_num) {
  546. if (len < min_length)
  547. break;
  548. if (length)
  549. *length = len;
  550. return p; /* start of actual option data */
  551. }
  552. p += len;
  553. }
  554. return NULL; /* Not found */
  555. }
  556. static uint8_t *add_dhcp_option_byte(uint8_t *opt, uint8_t type, uint8_t value)
  557. {
  558. *opt++ = type;
  559. *opt++ = 1;
  560. *opt++ = value;
  561. return opt;
  562. }
  563. static uint8_t *add_dhcp_option_bytes(uint8_t *opt, uint8_t type, void *value, uint8_t len)
  564. {
  565. *opt++ = type;
  566. if (len) {
  567. *opt++ = len;
  568. memcpy(opt, value, len);
  569. }
  570. return opt+len;
  571. }
  572. /* Find a free DHCP lease, or a lease already assigned to 'hwaddr' */
  573. static dhcp_lease_t *find_lease_slot(server_state_t* state, uint8_t *hwaddr)
  574. {
  575. dhcp_lease_t *empty_lease = NULL;
  576. for (int i = 0; i < state->max_leases; i++) {
  577. if (!state->leases[i].active && !empty_lease)
  578. empty_lease = &state->leases[i];
  579. else if (memcmp(hwaddr, state->leases[i].hwaddr, 6) == 0)
  580. return &state->leases[i];
  581. }
  582. return empty_lease;
  583. }