dhcp_client.c 11 KB

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