dhcp_client.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462
  1. #include "luat_base.h"
  2. #include "luat_mem.h"
  3. #include "luat_mcu.h"
  4. #if 1
  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. uint16_t escape_time = 0;
  16. if (dhcp->last_tx_time)
  17. {
  18. escape_time = (luat_mcu_tick64_ms() - dhcp->last_tx_time) / 1000;
  19. }
  20. BytesPut8ToBuf(out, DHCP_BOOTREQUEST);
  21. BytesPut8ToBuf(out, DHCP_HTYPE_ETH);
  22. BytesPut8ToBuf(out, 6);
  23. BytesPut8ToBuf(out, 0);
  24. BytesPutBe32ToBuf(out, dhcp->xid);
  25. BytesPutBe16ToBuf(out, escape_time);
  26. BytesPutBe16ToBuf(out, flag);
  27. BytesPutLe32ToBuf(out, dhcp->ip);
  28. BytesPutLe32ToBuf(out, 0);
  29. BytesPutLe32ToBuf(out, 0);
  30. BytesPutLe32ToBuf(out, 0);
  31. OS_BufferWrite(out, dhcp->mac, 6);
  32. memset(out->Data + out->Pos, 0, 10 + 64 + 128);
  33. out->Pos += 10 + 64 + 128;
  34. BytesPutBe32ToBuf(out, DHCP_MAGIC_COOKIE);
  35. }
  36. void ip4_dhcp_msg_add_bytes_option(uint8_t id, uint8_t *data, uint8_t len, Buffer_Struct *out)
  37. {
  38. BytesPut8ToBuf(out, id);
  39. BytesPut8ToBuf(out, len);
  40. OS_BufferWrite(out, data, len);
  41. }
  42. void ip4_dhcp_msg_add_client_id_option(uint8_t id, uint8_t *data, uint8_t len, Buffer_Struct *out)
  43. {
  44. BytesPut8ToBuf(out, id);
  45. BytesPut8ToBuf(out, len + 1);
  46. BytesPut8ToBuf(out, 1);
  47. OS_BufferWrite(out, data, len);
  48. }
  49. void ip4_dhcp_msg_add_ip_option(uint8_t id, uint32_t ip, Buffer_Struct *out)
  50. {
  51. BytesPut8ToBuf(out, id);
  52. BytesPut8ToBuf(out, 4);
  53. BytesPutLe32ToBuf(out, ip);
  54. }
  55. void ip4_dhcp_msg_add_integer_option(uint8_t id, uint8_t len, uint32_t value, Buffer_Struct *out)
  56. {
  57. BytesPut8ToBuf(out, id);
  58. BytesPut8ToBuf(out, len);
  59. switch (len)
  60. {
  61. case 1:
  62. BytesPut8ToBuf(out, value);
  63. break;
  64. case 2:
  65. BytesPutBe16ToBuf(out, value);
  66. break;
  67. default:
  68. BytesPutBe32ToBuf(out, value);
  69. break;
  70. }
  71. }
  72. void make_ip4_dhcp_discover_msg(dhcp_client_info_t *dhcp, Buffer_Struct *out)
  73. {
  74. uint8_t dhcp_discover_request_options[] = {
  75. DHCP_OPTION_SUBNET_MASK,
  76. DHCP_OPTION_ROUTER,
  77. DHCP_OPTION_BROADCAST,
  78. DHCP_OPTION_SERVER_ID,
  79. DHCP_OPTION_LEASE_TIME,
  80. DHCP_OPTION_IP_TTL,
  81. };
  82. out->Pos = 0;
  83. dhcp->xid++;
  84. make_ip4_dhcp_msg_base(dhcp, 0x8000, out);
  85. ip4_dhcp_msg_add_integer_option(DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN, DHCP_DISCOVER, out);
  86. ip4_dhcp_msg_add_bytes_option(DHCP_OPTION_PARAMETER_REQUEST_LIST, dhcp_discover_request_options, sizeof(dhcp_discover_request_options), out);
  87. ip4_dhcp_msg_add_bytes_option(DHCP_OPTION_HOSTNAME, (uint8_t*)dhcp->name, strlen(dhcp->name), out);
  88. ip4_dhcp_msg_add_client_id_option(DHCP_OPTION_CLIENT_ID, (uint8_t*)dhcp->mac, 6, out);
  89. BytesPut8ToBuf(out, 0xff);
  90. if (out->Pos < (DHCP_MSG_LEN + 72))
  91. {
  92. out->Pos = (DHCP_MSG_LEN + 72);
  93. }
  94. else
  95. {
  96. out->Pos = (out->Pos + (4 - 1)) & (~(4 - 1));
  97. }
  98. }
  99. void make_ip4_dhcp_select_msg(dhcp_client_info_t *dhcp, uint16_t flag, Buffer_Struct *out)
  100. {
  101. uint8_t dhcp_discover_request_options[] = {
  102. DHCP_OPTION_SUBNET_MASK,
  103. DHCP_OPTION_ROUTER,
  104. DHCP_OPTION_DNS_SERVER,
  105. 15,
  106. 31,33,43,44,46,47,
  107. DHCP_OPTION_SERVER_ID,
  108. DHCP_OPTION_LEASE_TIME,
  109. 119,121,249,252
  110. //DHCP_OPTION_138,
  111. };
  112. out->Pos = 0;
  113. uint8_t full_name[35] = {0};
  114. make_ip4_dhcp_msg_base(dhcp, flag, out);
  115. ip4_dhcp_msg_add_integer_option(DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN, DHCP_REQUEST, out);
  116. ip4_dhcp_msg_add_client_id_option(DHCP_OPTION_CLIENT_ID, (uint8_t*)dhcp->mac, 6, out);
  117. ip4_dhcp_msg_add_ip_option(DHCP_OPTION_REQUESTED_IP, dhcp->temp_ip, out);
  118. if (!flag)
  119. {
  120. ip4_dhcp_msg_add_ip_option(DHCP_OPTION_SERVER_ID, dhcp->server_ip, out);
  121. }
  122. ip4_dhcp_msg_add_bytes_option(DHCP_OPTION_HOSTNAME, (uint8_t*)dhcp->name, strlen(dhcp->name), out);
  123. memcpy(full_name + 3, (uint8_t*)dhcp->name, strlen(dhcp->name));
  124. ip4_dhcp_msg_add_bytes_option(81, full_name, strlen(dhcp->name) + 3, out);
  125. ip4_dhcp_msg_add_bytes_option(60, (uint8_t *)"MSFT 5.0", 8, out);
  126. ip4_dhcp_msg_add_bytes_option(DHCP_OPTION_PARAMETER_REQUEST_LIST, dhcp_discover_request_options, sizeof(dhcp_discover_request_options), out);
  127. BytesPut8ToBuf(out, 0xff);
  128. }
  129. //void make_ip4_dhcp_info_msg(dhcp_client_info_t *dhcp, Buffer_Struct *out)
  130. //{
  131. // uint8_t dhcp_discover_request_options[] = {
  132. // DHCP_OPTION_SUBNET_MASK,
  133. // DHCP_OPTION_ROUTER,
  134. // DHCP_OPTION_BROADCAST,
  135. // DHCP_OPTION_SERVER_ID,
  136. // DHCP_OPTION_LEASE_TIME,
  137. // DHCP_OPTION_DNS_SERVER,
  138. // DHCP_OPTION_IP_TTL,
  139. // DHCP_OPTION_138,
  140. // };
  141. // out->Pos = 0;
  142. // dhcp->xid++;
  143. // make_ip4_dhcp_msg_base(dhcp, 0x8000, out);
  144. // ip4_dhcp_msg_add_integer_option(DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN, DHCP_INFORM, out);
  145. // ip4_dhcp_msg_add_bytes_option(DHCP_OPTION_HOSTNAME, (uint8_t*)dhcp->name, strlen(dhcp->name), out);
  146. // ip4_dhcp_msg_add_client_id_option(DHCP_OPTION_CLIENT_ID, (uint8_t*)dhcp->mac, 6, out);
  147. // ip4_dhcp_msg_add_bytes_option(DHCP_OPTION_PARAMETER_REQUEST_LIST, dhcp_discover_request_options, sizeof(dhcp_discover_request_options), out);
  148. // BytesPut8ToBuf(out, 0xff);
  149. //}
  150. void make_ip4_dhcp_decline_msg(dhcp_client_info_t *dhcp, Buffer_Struct *out)
  151. {
  152. out->Pos = 0;
  153. dhcp->xid++;
  154. make_ip4_dhcp_msg_base(dhcp, 0, out);
  155. ip4_dhcp_msg_add_integer_option(DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN, DHCP_DECLINE, out);
  156. ip4_dhcp_msg_add_ip_option(DHCP_OPTION_REQUESTED_IP, dhcp->temp_ip, out);
  157. ip4_dhcp_msg_add_ip_option(DHCP_OPTION_SERVER_ID, dhcp->server_ip, out);
  158. ip4_dhcp_msg_add_bytes_option(DHCP_OPTION_HOSTNAME, (uint8_t*)dhcp->name, strlen(dhcp->name), out);
  159. ip4_dhcp_msg_add_client_id_option(DHCP_OPTION_CLIENT_ID, (uint8_t*)dhcp->mac, 6, out);
  160. BytesPut8ToBuf(out, 0xff);
  161. }
  162. int analyze_ip4_dhcp(dhcp_client_info_t *dhcp, Buffer_Struct *in)
  163. {
  164. int ack = 0;
  165. uint64_t lease_time;
  166. if (in->Data[0] != DHCP_BOOTREPLY)
  167. {
  168. LLOGD("head error");
  169. return -1;
  170. }
  171. if (BytesGetBe32(&in->Data[DHCP_MSG_LEN]) != DHCP_MAGIC_COOKIE)
  172. {
  173. LLOGD("cookie error");
  174. return -2;
  175. }
  176. if (BytesGetBe32(&in->Data[4]) != dhcp->xid)
  177. {
  178. LLOGD("xid error %x,%x", BytesGetBe32(&in->Data[4]), dhcp->xid);
  179. if (BytesGetBe32(&in->Data[4]) == (dhcp->xid - 1))
  180. {
  181. LLOGD("maybe get same ack, drop");
  182. return 0;
  183. }
  184. LLOGD("xid error %x,%x", BytesGetBe32(&in->Data[4]), dhcp->xid);
  185. return -3;
  186. }
  187. if (memcmp(dhcp->mac, &in->Data[28], 6))
  188. {
  189. LLOGD("mac error");
  190. return -4;
  191. }
  192. dhcp->temp_ip = BytesGetLe32(&in->Data[16]);
  193. LLOGD("find ip %x %d.%d.%d.%d", dhcp->temp_ip, in->Data[16], in->Data[17], in->Data[18], in->Data[19]);
  194. in->Pos = DHCP_OPTIONS_OFS;
  195. while (in->Pos < in->MaxLen)
  196. {
  197. __CHECK:
  198. switch(in->Data[in->Pos])
  199. {
  200. case DHCP_OPTION_MESSAGE_TYPE:
  201. ack = in->Data[in->Pos + 2];
  202. break;
  203. case DHCP_OPTION_SERVER_ID:
  204. dhcp->server_ip = BytesGetLe32(&in->Data[in->Pos + 2]);
  205. break;
  206. case DHCP_OPTION_LEASE_TIME:
  207. if (DHCP_ACK == ack)
  208. {
  209. dhcp->lease_time = BytesGetBe32(&in->Data[in->Pos + 2]);
  210. lease_time = dhcp->lease_time;
  211. lease_time *= 1000;
  212. dhcp->lease_end_time = luat_mcu_tick64_ms() + lease_time;
  213. dhcp->lease_p1_time = dhcp->lease_end_time - (lease_time >> 1);
  214. dhcp->lease_p2_time = dhcp->lease_end_time - (lease_time >> 3);
  215. }
  216. break;
  217. case DHCP_OPTION_SUBNET_MASK:
  218. dhcp->submask = BytesGetLe32(&in->Data[in->Pos + 2]);
  219. break;
  220. case DHCP_OPTION_ROUTER:
  221. dhcp->gateway = BytesGetLe32(&in->Data[in->Pos + 2]);
  222. break;
  223. case DHCP_OPTION_DNS_SERVER:
  224. dhcp->dns_server[0] = BytesGetLe32(&in->Data[in->Pos + 2]);
  225. dhcp->dns_server[1] = (in->Data[in->Pos + 1] >= 8)?BytesGetLe32(&in->Data[in->Pos + 6]):0;
  226. break;
  227. case DHCP_OPTION_PAD:
  228. in->Pos++;
  229. goto __CHECK;
  230. break;
  231. case DHCP_OPTION_END:
  232. return ack;
  233. default:
  234. //LLOGD("jump %d,%d", in->Data[in->Pos], in->Data[in->Pos+1]);
  235. break;
  236. }
  237. in->Pos += 2 + in->Data[in->Pos+1];
  238. }
  239. return ack;
  240. }
  241. int ip4_dhcp_run(dhcp_client_info_t *dhcp, Buffer_Struct *in, Buffer_Struct *out, uint32_t *remote_ip)
  242. {
  243. uint16_t flag = 0x8000;
  244. *remote_ip = 0xffffffff;
  245. int result = 0;
  246. uint64_t tnow = luat_mcu_tick64_ms();
  247. LLOGD("dhcp state %d %lld %lld %lld", dhcp->state, tnow, dhcp->lease_p1_time, dhcp->lease_p2_time);
  248. if (in)
  249. {
  250. result = analyze_ip4_dhcp(dhcp, in);
  251. LLOGD("result %d", result);
  252. if (result > 0)
  253. {
  254. if (result == DHCP_NAK)
  255. {
  256. dhcp->state = DHCP_STATE_DISCOVER;
  257. dhcp->temp_ip = 0;
  258. dhcp->server_ip = 0;
  259. dhcp->submask = 0;
  260. dhcp->gateway = 0;
  261. dhcp->ip = 0;
  262. dhcp->last_tx_time = 0;
  263. dhcp->lease_p1_time = 0;
  264. dhcp->lease_p2_time = 0;
  265. dhcp->weak_temp_ip = 0;
  266. dhcp->weak_server_ip = 0;
  267. }
  268. }
  269. else
  270. {
  271. return -1;
  272. }
  273. }
  274. // LLOGD("%d,%d", dhcp->state, result);
  275. switch(dhcp->state)
  276. {
  277. case DHCP_STATE_WAIT_LEASE_P1:
  278. if (tnow >= dhcp->lease_p1_time)
  279. {
  280. flag = 0;
  281. *remote_ip = dhcp->server_ip;
  282. dhcp->state = DHCP_STATE_WAIT_LEASE_P1_ACK;
  283. goto DHCP_NEED_REQUIRE;
  284. }
  285. break;
  286. case DHCP_STATE_WAIT_LEASE_P1_ACK:
  287. if (in && (result == DHCP_ACK))
  288. {
  289. LLOGD("lease p1 require ip ok");
  290. dhcp->state = DHCP_STATE_WAIT_LEASE_P1;
  291. break;
  292. }
  293. if (luat_mcu_tick64_ms() >= (dhcp->last_tx_time + 2500))
  294. {
  295. LLOGD("lease p1 require ip long time no ack");
  296. dhcp->state = DHCP_STATE_WAIT_LEASE_P2;
  297. }
  298. break;
  299. case DHCP_STATE_WAIT_LEASE_P2:
  300. if (tnow >= dhcp->lease_p2_time)
  301. {
  302. dhcp->state = DHCP_STATE_WAIT_SELECT_ACK;
  303. goto DHCP_NEED_REQUIRE;
  304. }
  305. break;
  306. case DHCP_STATE_WAIT_LEASE_P2_ACK:
  307. if (in && (result == DHCP_ACK))
  308. {
  309. LLOGD("lease p2 require ip ok");
  310. dhcp->state = DHCP_STATE_WAIT_LEASE_P1;
  311. break;
  312. }
  313. if (tnow >= (dhcp->last_tx_time + 2500))
  314. {
  315. LLOGD("lease p2 require ip long time no ack");
  316. dhcp->state = DHCP_STATE_WAIT_LEASE_END;
  317. }
  318. break;
  319. case DHCP_STATE_WAIT_LEASE_END:
  320. if (tnow >= dhcp->lease_end_time)
  321. {
  322. dhcp->state = DHCP_STATE_WAIT_SELECT_ACK;
  323. goto DHCP_NEED_REQUIRE;
  324. }
  325. break;
  326. // case DHCP_STATE_WAIT_REQUIRE_ACK:
  327. // if (in && (result == DHCP_ACK))
  328. // {
  329. // LLOGD("require ip ok");
  330. // dhcp->state = DHCP_STATE_WAIT_LEASE_P1;
  331. // break;
  332. // }
  333. // if (luat_mcu_tick64_ms() >= (dhcp->last_tx_time + 2500))
  334. // {
  335. // LLOGD("require 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_DISCOVER:
  344. LLOGD("dhcp discover");
  345. OS_ReInitBuffer(out, 512);
  346. make_ip4_dhcp_discover_msg(dhcp, out);
  347. dhcp->last_tx_time = luat_mcu_tick64_ms();
  348. dhcp->state = DHCP_STATE_WAIT_OFFER;
  349. break;
  350. case DHCP_STATE_WAIT_OFFER:
  351. if (in && (result == DHCP_OFFER))
  352. {
  353. LLOGD("select offer, wait ack");
  354. dhcp->state = DHCP_STATE_WAIT_SELECT_ACK;
  355. dhcp->wait_selec_ack_cnt = 0;
  356. goto DHCP_NEED_REQUIRE;
  357. }
  358. if (tnow >= (dhcp->last_tx_time + (dhcp->discover_cnt * 500) + 900))
  359. {
  360. LLOGD("long time no offer, resend");
  361. dhcp->discover_cnt++;
  362. OS_ReInitBuffer(out, 512);
  363. make_ip4_dhcp_discover_msg(dhcp, out);
  364. dhcp->last_tx_time = luat_mcu_tick64_ms();
  365. }
  366. break;
  367. case DHCP_STATE_WAIT_SELECT_ACK:
  368. if (in && (result == DHCP_ACK))
  369. {
  370. // LLOGD("need check ip %x,%x,%x,%x", dhcp->temp_ip, dhcp->submask, dhcp->gateway, dhcp->server_ip);
  371. dhcp->ip = dhcp->temp_ip;
  372. dhcp->state = DHCP_STATE_CHECK;
  373. dhcp->weak_temp_ip = 0;
  374. dhcp->weak_server_ip = 0;
  375. LLOGD("DHCP get ip ready");
  376. break;
  377. }
  378. if (dhcp->wait_selec_ack_cnt > 3)
  379. {
  380. LLOGD("select ip long time no ack");
  381. if ((dhcp->weak_temp_ip == dhcp->temp_ip) && (dhcp->weak_server_ip == dhcp->server_ip))
  382. {
  383. LLOGD("get same ip and server, maybe dhcp server error, use old ip");
  384. dhcp->ip = dhcp->temp_ip;
  385. dhcp->state = DHCP_STATE_CHECK;
  386. dhcp->weak_temp_ip = 0;
  387. dhcp->weak_server_ip = 0;
  388. break;
  389. }
  390. else
  391. {
  392. dhcp->weak_temp_ip = dhcp->temp_ip;
  393. dhcp->weak_server_ip = dhcp->server_ip;
  394. }
  395. OS_ReInitBuffer(out, 512);
  396. make_ip4_dhcp_discover_msg(dhcp, out);
  397. dhcp->last_tx_time = luat_mcu_tick64_ms();
  398. dhcp->discover_cnt = 0;
  399. dhcp->state = DHCP_STATE_WAIT_OFFER;
  400. }
  401. else
  402. {
  403. if (luat_mcu_tick64_ms() >= (dhcp->last_tx_time + 1900 * (dhcp->wait_selec_ack_cnt + 1)))
  404. {
  405. dhcp->wait_selec_ack_cnt++;
  406. LLOGD("select ip no ack,resend %d", dhcp->wait_selec_ack_cnt);
  407. goto DHCP_NEED_REQUIRE;
  408. }
  409. }
  410. break;
  411. case DHCP_STATE_REQUIRE:
  412. case DHCP_STATE_SELECT:
  413. dhcp->state = DHCP_STATE_WAIT_SELECT_ACK;
  414. goto DHCP_NEED_REQUIRE;
  415. break;
  416. case DHCP_STATE_CHECK:
  417. break;
  418. case DHCP_STATE_DECLINE:
  419. dhcp->weak_temp_ip = 0;
  420. dhcp->weak_server_ip = 0;
  421. flag = 0;
  422. *remote_ip = dhcp->server_ip;
  423. OS_ReInitBuffer(out, 512);
  424. make_ip4_dhcp_decline_msg(dhcp, out);
  425. dhcp->last_tx_time = luat_mcu_tick64_ms();
  426. dhcp->state = DHCP_STATE_DISCOVER;
  427. break;
  428. case DHCP_STATE_NOT_WORK:
  429. break;
  430. }
  431. return 0;
  432. DHCP_NEED_REQUIRE:
  433. OS_ReInitBuffer(out, 512);
  434. make_ip4_dhcp_select_msg(dhcp, flag, out);
  435. dhcp->last_tx_time = luat_mcu_tick64_ms();
  436. return 0;
  437. }
  438. #endif