dhcp_client.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384
  1. #include "luat_base.h"
  2. #include "luat_malloc.h"
  3. #include "luat_mcu.h"
  4. #ifdef LUAT_USE_DHCP
  5. #include "luat_network_adapter.h"
  6. #include "dhcp_def.h"
  7. #define LUAT_LOG_TAG "DHCP"
  8. #include "luat_log.h"
  9. #define DHCP_OPTION_138 138
  10. //extern void DBG_Printf(const char* format, ...);
  11. //extern void DBG_HexPrintf(void *Data, unsigned int len);
  12. //#define DBG(x,y...) DBG_Printf("%s %d:"x"\r\n", __FUNCTION__,__LINE__,##y)
  13. void make_ip4_dhcp_msg_base(dhcp_client_info_t *dhcp, uint16_t flag, Buffer_Struct *out)
  14. {
  15. dhcp->xid++;
  16. BytesPut8ToBuf(out, DHCP_BOOTREQUEST);
  17. BytesPut8ToBuf(out, DHCP_HTYPE_ETH);
  18. BytesPut8ToBuf(out, 6);
  19. BytesPut8ToBuf(out, 0);
  20. BytesPutBe32ToBuf(out, dhcp->xid);
  21. BytesPutBe16ToBuf(out, 0);
  22. BytesPutBe16ToBuf(out, flag);
  23. BytesPutLe32ToBuf(out, dhcp->ip);
  24. BytesPutLe32ToBuf(out, 0);
  25. BytesPutLe32ToBuf(out, 0);
  26. BytesPutLe32ToBuf(out, 0);
  27. OS_BufferWrite(out, dhcp->mac, 6);
  28. memset(out->Data + out->Pos, 0, 10 + 64 + 128);
  29. out->Pos += 10 + 64 + 128;
  30. BytesPutBe32ToBuf(out, DHCP_MAGIC_COOKIE);
  31. }
  32. void ip4_dhcp_msg_add_bytes_option(uint8_t id, uint8_t *data, uint8_t len, Buffer_Struct *out)
  33. {
  34. BytesPut8ToBuf(out, id);
  35. BytesPut8ToBuf(out, len);
  36. OS_BufferWrite(out, data, len);
  37. }
  38. void ip4_dhcp_msg_add_client_id_option(uint8_t id, uint8_t *data, uint8_t len, Buffer_Struct *out)
  39. {
  40. BytesPut8ToBuf(out, id);
  41. BytesPut8ToBuf(out, len + 1);
  42. BytesPut8ToBuf(out, 1);
  43. OS_BufferWrite(out, data, len);
  44. }
  45. void ip4_dhcp_msg_add_ip_option(uint8_t id, uint32_t ip, Buffer_Struct *out)
  46. {
  47. BytesPut8ToBuf(out, id);
  48. BytesPut8ToBuf(out, 4);
  49. BytesPutLe32ToBuf(out, ip);
  50. }
  51. void ip4_dhcp_msg_add_integer_option(uint8_t id, uint8_t len, uint32_t value, Buffer_Struct *out)
  52. {
  53. BytesPut8ToBuf(out, id);
  54. BytesPut8ToBuf(out, len);
  55. switch (len)
  56. {
  57. case 1:
  58. BytesPut8ToBuf(out, value);
  59. break;
  60. case 2:
  61. BytesPutBe16ToBuf(out, value);
  62. break;
  63. default:
  64. BytesPutBe32ToBuf(out, value);
  65. break;
  66. }
  67. }
  68. void make_ip4_dhcp_discover_msg(dhcp_client_info_t *dhcp, Buffer_Struct *out)
  69. {
  70. uint8_t dhcp_discover_request_options[] = {
  71. DHCP_OPTION_SUBNET_MASK,
  72. DHCP_OPTION_ROUTER,
  73. DHCP_OPTION_BROADCAST,
  74. DHCP_OPTION_SERVER_ID,
  75. DHCP_OPTION_LEASE_TIME,
  76. DHCP_OPTION_IP_TTL,
  77. };
  78. out->Pos = 0;
  79. make_ip4_dhcp_msg_base(dhcp, 0x8000, out);
  80. ip4_dhcp_msg_add_integer_option(DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN, DHCP_DISCOVER, out);
  81. ip4_dhcp_msg_add_bytes_option(DHCP_OPTION_PARAMETER_REQUEST_LIST, dhcp_discover_request_options, sizeof(dhcp_discover_request_options), out);
  82. ip4_dhcp_msg_add_bytes_option(DHCP_OPTION_HOSTNAME, (uint8_t*)dhcp->name, strlen(dhcp->name), out);
  83. ip4_dhcp_msg_add_client_id_option(DHCP_OPTION_CLIENT_ID, (uint8_t*)dhcp->mac, 6, out);
  84. BytesPut8ToBuf(out, 0xff);
  85. if (out->Pos < (DHCP_MSG_LEN + 72))
  86. {
  87. out->Pos = (DHCP_MSG_LEN + 72);
  88. }
  89. else
  90. {
  91. out->Pos = (out->Pos + (4 - 1)) & (~(4 - 1));
  92. }
  93. }
  94. void make_ip4_dhcp_select_msg(dhcp_client_info_t *dhcp, uint16_t flag, Buffer_Struct *out)
  95. {
  96. uint8_t dhcp_discover_request_options[] = {
  97. DHCP_OPTION_SUBNET_MASK,
  98. DHCP_OPTION_ROUTER,
  99. DHCP_OPTION_BROADCAST,
  100. DHCP_OPTION_SERVER_ID,
  101. DHCP_OPTION_LEASE_TIME,
  102. DHCP_OPTION_DNS_SERVER,
  103. DHCP_OPTION_IP_TTL,
  104. DHCP_OPTION_138,
  105. };
  106. out->Pos = 0;
  107. make_ip4_dhcp_msg_base(dhcp, flag, out);
  108. ip4_dhcp_msg_add_integer_option(DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN, DHCP_REQUEST, out);
  109. ip4_dhcp_msg_add_ip_option(DHCP_OPTION_REQUESTED_IP, dhcp->temp_ip, out);
  110. if (!flag)
  111. {
  112. ip4_dhcp_msg_add_ip_option(DHCP_OPTION_SERVER_ID, dhcp->server_ip, out);
  113. }
  114. ip4_dhcp_msg_add_bytes_option(DHCP_OPTION_PARAMETER_REQUEST_LIST, dhcp_discover_request_options, sizeof(dhcp_discover_request_options), out);
  115. ip4_dhcp_msg_add_bytes_option(DHCP_OPTION_HOSTNAME, (uint8_t*)dhcp->name, strlen(dhcp->name), out);
  116. ip4_dhcp_msg_add_client_id_option(DHCP_OPTION_CLIENT_ID, (uint8_t*)dhcp->mac, 6, out);
  117. BytesPut8ToBuf(out, 0xff);
  118. }
  119. void make_ip4_dhcp_decline_msg(dhcp_client_info_t *dhcp, Buffer_Struct *out)
  120. {
  121. out->Pos = 0;
  122. make_ip4_dhcp_msg_base(dhcp, 0, out);
  123. ip4_dhcp_msg_add_integer_option(DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN, DHCP_DECLINE, out);
  124. ip4_dhcp_msg_add_ip_option(DHCP_OPTION_REQUESTED_IP, dhcp->temp_ip, out);
  125. ip4_dhcp_msg_add_ip_option(DHCP_OPTION_SERVER_ID, dhcp->server_ip, out);
  126. ip4_dhcp_msg_add_bytes_option(DHCP_OPTION_HOSTNAME, (uint8_t*)dhcp->name, strlen(dhcp->name), out);
  127. ip4_dhcp_msg_add_client_id_option(DHCP_OPTION_CLIENT_ID, (uint8_t*)dhcp->mac, 6, out);
  128. BytesPut8ToBuf(out, 0xff);
  129. }
  130. int analyze_ip4_dhcp(dhcp_client_info_t *dhcp, Buffer_Struct *in)
  131. {
  132. int ack = 0;
  133. uint64_t lease_time;
  134. if (in->Data[0] != DHCP_BOOTREPLY)
  135. {
  136. LLOGD("head error");
  137. return -1;
  138. }
  139. if (BytesGetBe32(&in->Data[DHCP_MSG_LEN]) != DHCP_MAGIC_COOKIE)
  140. {
  141. LLOGD("cookie error");
  142. return -2;
  143. }
  144. if (BytesGetBe32(&in->Data[4]) != dhcp->xid)
  145. {
  146. LLOGD("xid error %x,%x", BytesGetBe32(&in->Data[4]), dhcp->xid);
  147. return -3;
  148. }
  149. if (memcmp(dhcp->mac, &in->Data[28], 6))
  150. {
  151. LLOGD("mac error");
  152. return -4;
  153. }
  154. dhcp->temp_ip = BytesGetLe32(&in->Data[16]);
  155. LLOGD("find ip %x", dhcp->temp_ip);
  156. in->Pos = DHCP_OPTIONS_OFS;
  157. while (in->Pos < in->MaxLen)
  158. {
  159. __CHECK:
  160. switch(in->Data[in->Pos])
  161. {
  162. case DHCP_OPTION_MESSAGE_TYPE:
  163. ack = in->Data[in->Pos + 2];
  164. break;
  165. case DHCP_OPTION_SERVER_ID:
  166. dhcp->server_ip = BytesGetLe32(&in->Data[in->Pos + 2]);
  167. break;
  168. case DHCP_OPTION_LEASE_TIME:
  169. if (DHCP_ACK == ack)
  170. {
  171. dhcp->lease_time = BytesGetBe32(&in->Data[in->Pos + 2]);
  172. lease_time = dhcp->lease_time;
  173. lease_time *= 1000;
  174. dhcp->lease_end_time = luat_mcu_tick64_ms() + lease_time;
  175. dhcp->lease_p1_time = dhcp->lease_end_time - (lease_time >> 1);
  176. dhcp->lease_p2_time = dhcp->lease_end_time - (lease_time >> 3);
  177. }
  178. break;
  179. case DHCP_OPTION_SUBNET_MASK:
  180. dhcp->submask = BytesGetLe32(&in->Data[in->Pos + 2]);
  181. break;
  182. case DHCP_OPTION_ROUTER:
  183. dhcp->gateway = BytesGetLe32(&in->Data[in->Pos + 2]);
  184. break;
  185. case DHCP_OPTION_DNS_SERVER:
  186. dhcp->dns_server[0] = BytesGetLe32(&in->Data[in->Pos + 2]);
  187. dhcp->dns_server[1] = (in->Data[in->Pos + 1] >= 8)?BytesGetLe32(&in->Data[in->Pos + 6]):0;
  188. break;
  189. case DHCP_OPTION_PAD:
  190. in->Pos++;
  191. goto __CHECK;
  192. break;
  193. case DHCP_OPTION_END:
  194. return ack;
  195. default:
  196. LLOGD("jump %d,%d", in->Data[in->Pos], in->Data[in->Pos+1]);
  197. break;
  198. }
  199. in->Pos += 2 + in->Data[in->Pos+1];
  200. }
  201. return ack;
  202. }
  203. int ip4_dhcp_run(dhcp_client_info_t *dhcp, Buffer_Struct *in, Buffer_Struct *out, uint32_t *remote_ip)
  204. {
  205. uint16_t flag = 0x8000;
  206. *remote_ip = 0xffffffff;
  207. int result = 0;
  208. if (in)
  209. {
  210. result = analyze_ip4_dhcp(dhcp, in);
  211. LLOGD("result %d", result);
  212. if (result > 0)
  213. {
  214. if (result == DHCP_NAK)
  215. {
  216. dhcp->state = DHCP_STATE_DISCOVER;
  217. dhcp->temp_ip = 0;
  218. dhcp->server_ip = 0;
  219. dhcp->submask = 0;
  220. dhcp->gateway = 0;
  221. dhcp->ip = 0;
  222. dhcp->last_tx_time = 0;
  223. dhcp->lease_p1_time = 0;
  224. dhcp->lease_p2_time = 0;
  225. }
  226. }
  227. else
  228. {
  229. return -1;
  230. }
  231. }
  232. // LLOGD("%d,%d", dhcp->state, result);
  233. switch(dhcp->state)
  234. {
  235. case DHCP_STATE_WAIT_LEASE_P1:
  236. if (luat_mcu_tick64_ms() >= dhcp->lease_p1_time)
  237. {
  238. flag = 0;
  239. *remote_ip = dhcp->server_ip;
  240. dhcp->state = DHCP_STATE_WAIT_LEASE_P1_ACK;
  241. goto DHCP_NEED_REQUIRE;
  242. }
  243. break;
  244. case DHCP_STATE_WAIT_LEASE_P1_ACK:
  245. if (in && (result == DHCP_ACK))
  246. {
  247. LLOGD("lease p1 require ip ok");
  248. dhcp->state = DHCP_STATE_WAIT_LEASE_P1;
  249. break;
  250. }
  251. if (luat_mcu_tick64_ms() >= (dhcp->last_tx_time + 2500))
  252. {
  253. LLOGD("lease p1 require ip long time no ack");
  254. dhcp->state = DHCP_STATE_WAIT_LEASE_P2;
  255. }
  256. break;
  257. case DHCP_STATE_WAIT_LEASE_P2:
  258. if (luat_mcu_tick64_ms() >= dhcp->lease_p2_time)
  259. {
  260. dhcp->state = DHCP_STATE_WAIT_SELECT_ACK;
  261. goto DHCP_NEED_REQUIRE;
  262. }
  263. break;
  264. case DHCP_STATE_WAIT_LEASE_P2_ACK:
  265. if (in && (result == DHCP_ACK))
  266. {
  267. LLOGD("lease p2 require ip ok");
  268. dhcp->state = DHCP_STATE_WAIT_LEASE_P1;
  269. break;
  270. }
  271. if (luat_mcu_tick64_ms() >= (dhcp->last_tx_time + 2500))
  272. {
  273. LLOGD("lease p2 require ip long time no ack");
  274. dhcp->state = DHCP_STATE_WAIT_LEASE_END;
  275. }
  276. break;
  277. case DHCP_STATE_WAIT_LEASE_END:
  278. if (luat_mcu_tick64_ms() >= dhcp->lease_end_time)
  279. {
  280. dhcp->state = DHCP_STATE_WAIT_SELECT_ACK;
  281. goto DHCP_NEED_REQUIRE;
  282. }
  283. break;
  284. // case DHCP_STATE_WAIT_REQUIRE_ACK:
  285. // if (in && (result == DHCP_ACK))
  286. // {
  287. // LLOGD("require ip ok");
  288. // dhcp->state = DHCP_STATE_WAIT_LEASE_P1;
  289. // break;
  290. // }
  291. // if (luat_mcu_tick64_ms() >= (dhcp->last_tx_time + 2500))
  292. // {
  293. // LLOGD("require ip long time no ack");
  294. // OS_ReInitBuffer(out, 512);
  295. // make_ip4_dhcp_discover_msg(dhcp, out);
  296. // dhcp->last_tx_time = luat_mcu_tick64_ms();
  297. // dhcp->discover_cnt = 0;
  298. // dhcp->state = DHCP_STATE_WAIT_OFFER;
  299. // }
  300. // break;
  301. case DHCP_STATE_DISCOVER:
  302. LLOGD("dhcp discover");
  303. OS_ReInitBuffer(out, 512);
  304. make_ip4_dhcp_discover_msg(dhcp, out);
  305. dhcp->last_tx_time = luat_mcu_tick64_ms();
  306. dhcp->state = DHCP_STATE_WAIT_OFFER;
  307. break;
  308. case DHCP_STATE_WAIT_OFFER:
  309. if (in && (result == DHCP_OFFER))
  310. {
  311. LLOGD("select offer, wait ack");
  312. dhcp->state = DHCP_STATE_WAIT_SELECT_ACK;
  313. goto DHCP_NEED_REQUIRE;
  314. }
  315. if (luat_mcu_tick64_ms() >= (dhcp->last_tx_time + (dhcp->discover_cnt * 500) + 900))
  316. {
  317. LLOGD("long time no offer, resend");
  318. dhcp->discover_cnt++;
  319. OS_ReInitBuffer(out, 512);
  320. make_ip4_dhcp_discover_msg(dhcp, out);
  321. dhcp->last_tx_time = luat_mcu_tick64_ms();
  322. }
  323. break;
  324. case DHCP_STATE_WAIT_SELECT_ACK:
  325. if (in && (result == DHCP_ACK))
  326. {
  327. // LLOGD("need check ip %x,%x,%x,%x", dhcp->temp_ip, dhcp->submask, dhcp->gateway, dhcp->server_ip);
  328. dhcp->ip = dhcp->temp_ip;
  329. dhcp->state = DHCP_STATE_CHECK;
  330. LLOGD("DHCP get ip ready");
  331. break;
  332. }
  333. if (luat_mcu_tick64_ms() >= (dhcp->last_tx_time + (dhcp->discover_cnt * 500) + 1100))
  334. {
  335. LLOGD("select ip long time no ack");
  336. OS_ReInitBuffer(out, 512);
  337. make_ip4_dhcp_discover_msg(dhcp, out);
  338. dhcp->last_tx_time = luat_mcu_tick64_ms();
  339. dhcp->discover_cnt = 0;
  340. dhcp->state = DHCP_STATE_WAIT_OFFER;
  341. }
  342. break;
  343. case DHCP_STATE_REQUIRE:
  344. case DHCP_STATE_SELECT:
  345. dhcp->state = DHCP_STATE_WAIT_SELECT_ACK;
  346. goto DHCP_NEED_REQUIRE;
  347. break;
  348. case DHCP_STATE_CHECK:
  349. break;
  350. case DHCP_STATE_DECLINE:
  351. flag = 0;
  352. *remote_ip = dhcp->server_ip;
  353. OS_ReInitBuffer(out, 512);
  354. make_ip4_dhcp_decline_msg(dhcp, out);
  355. dhcp->last_tx_time = luat_mcu_tick64_ms();
  356. dhcp->state = DHCP_STATE_DISCOVER;
  357. break;
  358. case DHCP_STATE_NOT_WORK:
  359. break;
  360. }
  361. return 0;
  362. DHCP_NEED_REQUIRE:
  363. OS_ReInitBuffer(out, 512);
  364. make_ip4_dhcp_select_msg(dhcp, flag, out);
  365. dhcp->last_tx_time = luat_mcu_tick64_ms();
  366. return 0;
  367. }
  368. #endif