WIZlib Library API  ver 1.0
WIZlib Library API User Menual
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
dhcp.c
Go to the documentation of this file.
1 
12 //#define FILE_LOG_SILENCE
13 #include "common/common.h"
14 #if (USE_DHCP == VAL_DISABLE)
15 #include "protocol/DHCP/dhcp.h"
16 #endif
17 
18 #define DHCP_SERVER_PORT 67 // from server to client
19 #define DHCP_CLIENT_PORT 68 // from client to server
20 
21 #define DHCP_BOOTREQUEST 1
22 #define DHCP_BOOTREPLY 2
23 #define DHCP_HTYPE10MB 1
24 #define DHCP_HTYPE100MB 2
25 #define DHCP_HLENETHERNET 6
26 #define DHCP_HOPS 0
27 #define DHCP_SECS 0
28 #define DHCP_UNICAST 0x0
29 #define DHCP_BROADCAST 0x8000
30 #define MAGIC_COOKIE 0x63825363
31 #define HOST_NAME "WIZnet"
32 
33 #define DHCP_MSG_DISCOVER 1 // DHCP message type
34 #define DHCP_MSG_OFFER 2
35 #define DHCP_MSG_REQUEST 3
36 #define DHCP_MSG_DECLINE 4
37 #define DHCP_MSG_ACK 5
38 #define DHCP_MSG_NAK 6
39 #define DHCP_MSG_RELEASE 7
40 
41 #define DHCP_START_RETRY_DELAY 60000 // tick
42 #define DHCP_RETRY_DELAY 5000 // tick
43 //#define DHCP_INTERVAL_OPEN_RETRY 1000 // tick
44 //#define DHCP_RECV_WAIT_TIME 3000 // tick
45 #define DHCP_OPEN_DELAY 0 // tick
46 #define DHCP_SEND_RETRY_COUNT 3
47 
48 #define IS_IP_SET(ip_p) (ip_p[0]+ip_p[1]+ip_p[2]+ip_p[3] != 0)
49 #define IS_TIME_PASSED(tick_v, time_v) (wizpf_tick_elapse(tick_v) > time_v)
50 #define SET_STATE(_new_state) do { \
51  DBGA("DHCP STATE: [%d] => [%d]", di.state, _new_state); \
52  di.state = _new_state; \
53 } while(0)
54 
55 enum { //DHCP option and value (cf. RFC1533)
56  padOption = 0,
57  subnetMask = 1,
58  timerOffset = 2,
59  routersOnSubnet = 3,
60  timeServer = 4,
61  nameServer = 5,
62  dns = 6,
63  logServer = 7,
64  cookieServer = 8,
65  lprServer = 9,
66  impressServer = 10,
67  resourceLocationServer = 11,
68  hostName = 12,
69  bootFileSize = 13,
70  meritDumpFile = 14,
71  domainName = 15,
72  swapServer = 16,
73  rootPath = 17,
74  extentionsPath = 18,
75  IPforwarding = 19,
76  nonLocalSourceRouting = 20,
77  policyFilter = 21,
78  maxDgramReasmSize = 22,
79  defaultIPTTL = 23,
80  pathMTUagingTimeout = 24,
81  pathMTUplateauTable = 25,
82  ifMTU = 26,
83  allSubnetsLocal = 27,
84  broadcastAddr = 28,
85  performMaskDiscovery = 29,
86  maskSupplier = 30,
87  performRouterDiscovery = 31,
88  routerSolicitationAddr = 32,
89  staticRoute = 33,
90  trailerEncapsulation = 34,
91  arpCacheTimeout = 35,
92  ethernetEncapsulation = 36,
93  tcpDefaultTTL = 37,
94  tcpKeepaliveInterval = 38,
95  tcpKeepaliveGarbage = 39,
96  nisDomainName = 40,
97  nisServers = 41,
98  ntpServers = 42,
99  vendorSpecificInfo = 43,
100  netBIOSnameServer = 44,
101  netBIOSdgramDistServer = 45,
102  netBIOSnodeType = 46,
103  netBIOSscope = 47,
104  xFontServer = 48,
105  xDisplayManager = 49,
106  dhcpRequestedIPaddr = 50,
107  dhcpIPaddrLeaseTime = 51,
108  dhcpOptionOverload = 52,
109  dhcpMessageType = 53,
110  dhcpServerIdentifier = 54,
111  dhcpParamRequest = 55,
112  dhcpMsg = 56,
113  dhcpMaxMsgSize = 57,
114  dhcpT1value = 58,
115  dhcpT2value = 59,
116  dhcpClassIdentifier = 60,
117  dhcpClientIdentifier = 61,
118  endOption = 255
119 };
120 
121 struct dhcp_msg {
122  uint8 op;
123  uint8 htype;
124  uint8 hlen;
125  uint8 hops;
126  uint32 xid;
127  uint16 secs;
128  uint16 flags;
129  uint8 ciaddr[4];
130  uint8 yiaddr[4];
131  uint8 siaddr[4];
132  uint8 giaddr[4];
133  uint8 chaddr[16];
134  uint8 sname[64];
135  uint8 file[128];
136  uint8 opt[312];
137 };
138 
139 struct dhcp_info {
140  uint8 srv_ip[4]; // Server IP Address - get from DHCP packet
141  uint8 srv_ip_real[4]; // Real Server IP Address - get from UDP info
142  uint8 sock;
143  dhcp_state state;
144  dhcp_action action;
145  uint32 lease_time;
146  uint32 renew_time;
147  uint32 rebind_time;
148  uint32 xid;
149  void_func ip_update;
150  void_func ip_conflict;
151 };
152 
153 static void dhcp_alarm_cb(int8 arg); // for alarm mode;
154 static void dhcp_async_cb(uint8 sock, uint8 item, int32 ret);
155 static void dhcp_run(void);
156 static void dhcp_fail(void);
157 static int8 recv_handler(void);
158 static int8 send_discover(void);
159 static int8 send_request(void);
160 //static int8 send_rel_dec(int8 msgtype);
161 //static int8 send_checker(void);
162 //static void default_ip_update(void);
163 //static void default_ip_conflict(void);
164 
165 
166 static wiz_NetInfo workinfo, storage;
167 static struct dhcp_info di;
168 static struct dhcp_msg dm;
169 static bool dhcp_alarm = FALSE;
170 static bool dhcp_async = FALSE;
171 static uint8 dhcp_run_cnt = 0;
172 static uint32 dhcp_run_tick = 0;
173 
174 
191 int8 dhcp_init(uint8 sock, void_func ip_update_hook, void_func ip_conflict_hook, wiz_NetInfo *def)
192 {
193  if(sock >= TOTAL_SOCK_NUM) {
194  ERRA("wrong socket number(%d)", sock);
195  return RET_NOK;
196  }
197 
198 #ifdef DHCP_AUTO
199  dhcp_alarm = TRUE;
200 #endif
201 #ifdef DHCP_ASYNC
202  dhcp_async = TRUE;
203 #endif
204 
205  memset(&di, 0, sizeof(di));
206  memcpy(&storage, def, sizeof(storage));
207  memset(&workinfo, 0, sizeof(workinfo));
208  memcpy(workinfo.mac, storage.mac, 6);
209  workinfo.dhcp = NETINFO_STATIC;
210  SetNetInfo(&workinfo);
211  di.xid = 0x12345678;
212  di.sock = sock;
213  if(ip_update_hook) di.ip_update = ip_update_hook;
214  if(ip_conflict_hook) di.ip_conflict = ip_conflict_hook;
215 
216  // ToDo: Remove setting zero IP & SN (set at start func)
217 
218  return RET_OK;
219 }
220 
234 int8 dhcp_manual(dhcp_action action, uint32 *renew, uint32 *rebind) // blocking function
235 {
236  dhcp_state curstt = di.state;
237 
238  if(dhcp_alarm == TRUE) return RET_NOK;
239 
240  while(curstt != DHCP_STATE_INIT && curstt != DHCP_STATE_BOUND) {
241  dhcp_run();
242  curstt = di.state;
243  }
244 
245  if(curstt == DHCP_STATE_INIT) {
246  di.action = DHCP_ACT_START;
247  memset(&workinfo, 0, sizeof(workinfo));
248  workinfo.dhcp = NETINFO_DHCP;
249  SetNetInfo(&workinfo);
250 
251  // ToDo: Set zero IP & SN
252 
253  do {
254  dhcp_run();
255  curstt = di.state;
256  } while((curstt != DHCP_STATE_INIT || di.action != DHCP_ACT_START)
257  && curstt != DHCP_STATE_BOUND);
258  if(curstt != DHCP_STATE_BOUND) return RET_NOK;
259  if(renew) *renew = di.renew_time;
260  if(rebind) *rebind = di.rebind_time;
261  } else if(curstt == DHCP_STATE_BOUND) {
262  if(action == DHCP_ACT_START) {
263  if(renew) *renew = 0;
264  if(rebind) *rebind = 0;
265  return RET_OK;
266  } else if(action == DHCP_ACT_RENEW) { // renew
267  SET_STATE(DHCP_STATE_SELECTING);
268  di.action = DHCP_ACT_RENEW;
269  di.xid++;
270  } else if(action == DHCP_ACT_REBIND) { // rebind
271  SET_STATE(DHCP_STATE_SELECTING);
272  di.action = DHCP_ACT_REBIND;
273  di.xid++;
274  } else {
275  ERRA("wrong action(%d)", action);
276  return RET_NOK;
277  }
278  curstt = di.state;
279  while(curstt != DHCP_STATE_INIT && curstt != DHCP_STATE_BOUND) {
280  dhcp_run();
281  curstt = di.state;
282  }
283  if(curstt != DHCP_STATE_BOUND) return RET_NOK;
284  if(renew) *renew = di.renew_time;
285  if(rebind) *rebind = di.rebind_time;
286  }
287 
288  return RET_OK;
289 }
290 
296 {
297  return di.state;
298 }
299 
315 void dhcp_set_storage(wiz_NetInfo *net) // Should be updated when MAC is changed
316 {
317  if(net == NULL) {
318  DBG("NULL arg");
319  return;
320  }
321 
322  if(net->mac[0]!=0 || net->mac[1]!=0 || net->mac[2]!=0 || net->mac[3]!=0 ||
323  net->mac[2]!=0 || net->mac[3]!=0) memcpy(storage.mac, net->mac, 6);
324  if(net->ip[0]!=0 || net->ip[1]!=0 || net->ip[2]!=0 || net->ip[3]!=0)
325  memcpy(storage.ip, net->ip, 4);
326  if(net->sn[0]!=0 || net->sn[1]!=0 || net->sn[2]!=0 || net->sn[3]!=0)
327  memcpy(storage.sn, net->sn, 4);
328  if(net->gw[0]!=0 || net->gw[1]!=0 || net->gw[2]!=0 || net->gw[3]!=0)
329  memcpy(storage.gw, net->gw, 4);
330  if(net->dns[0]!=0 || net->dns[1]!=0 || net->dns[2]!=0 || net->dns[3]!=0)
331  memcpy(storage.dns, net->dns, 4);
332 }
333 
343 {
344  if(net == NULL) {
345  DBG("NULL arg");
346  return;
347  }
348 
349  memcpy(net->mac, storage.mac, 6);
350  memcpy(net->ip, storage.ip, 4);
351  memcpy(net->sn, storage.sn, 4);
352  memcpy(net->gw, storage.gw, 4);
353  memcpy(net->dns, storage.dns, 4);
354 }
355 
365 {
366  di.action = DHCP_ACT_NONE;
367  SET_STATE(DHCP_STATE_INIT);
368 
369  if(net != NULL) {
370  if(net->ip[0]!=0 || net->ip[1]!=0 || net->ip[2]!=0 || net->ip[3]!=0)
371  memcpy(storage.ip, net->ip, 4);
372  else memcpy(net->ip, storage.ip, 4);
373  if(net->sn[0]!=0 || net->sn[1]!=0 || net->sn[2]!=0 || net->sn[3]!=0)
374  memcpy(storage.sn, net->sn, 4);
375  else memcpy(net->sn, storage.sn, 4);
376  if(net->gw[0]!=0 || net->gw[1]!=0 || net->gw[2]!=0 || net->gw[3]!=0)
377  memcpy(storage.gw, net->gw, 4);
378  else memcpy(net->gw, storage.gw, 4);
379  if(net->dns[0]!=0 || net->dns[1]!=0 || net->dns[2]!=0 || net->dns[3]!=0)
380  memcpy(storage.dns, net->dns, 4);
381  else memcpy(net->dns, storage.dns, 4);
382 
383  net->dhcp = NETINFO_STATIC;
384  SetNetInfo(net);
385  } else {
386  SetNetInfo(&storage);
387  memset(&workinfo, 0, sizeof(workinfo));
388  workinfo.dhcp = NETINFO_STATIC;
389  SetNetInfo(&workinfo);
390  }
391 
392  if(dhcp_alarm) alarm_del(dhcp_alarm_cb, -1);
393  //send_checker_NB();
394 }
395 
404 void dhcp_auto_start(void)
405 {
406  DBG("DHCP Start");
407  SET_STATE(DHCP_STATE_INIT);
408  di.action = DHCP_ACT_START;
409 
410  memset(&workinfo, 0, sizeof(workinfo));
411  workinfo.dhcp = NETINFO_DHCP;
412  SetNetInfo(&workinfo);
413 
414  // ToDo: Set zero IP & SN
415 
416  if(dhcp_alarm) alarm_set(10, dhcp_alarm_cb, 0);
417 }
418 
419 /* @} */
420 
421 static void dhcp_alarm_cb(int8 arg) // for DHCP auto mode
422 {
423  if(dhcp_alarm == FALSE) return;
424  if(arg == 0) {
425  if(di.state == DHCP_STATE_BOUND) {
426  alarm_set(wizpf_tick_conv(FALSE, di.renew_time), dhcp_alarm_cb, 1);
427  alarm_set(wizpf_tick_conv(FALSE, di.rebind_time), dhcp_alarm_cb, 2);
428  }
429  if(di.state == DHCP_STATE_FAILED) {
430  di.state = DHCP_STATE_INIT;
431  di.action = DHCP_ACT_START;
432  }
433  dhcp_run();
434  } else if(arg == 1) { // renew
435  SET_STATE(DHCP_STATE_SELECTING);
436  di.action = DHCP_ACT_RENEW;
437  di.xid++;
438  alarm_set(10, dhcp_alarm_cb, 0);
439  } else if(arg == 2) { // rebind
440  SET_STATE(DHCP_STATE_SELECTING);
441  di.action = DHCP_ACT_REBIND;
442  di.xid++;
443  alarm_set(10, dhcp_alarm_cb, 0);
444  }
445 }
446 
447 static void dhcp_async_cb(uint8 sock, uint8 item, int32 ret) // for async mode
448 {
449  switch(item) {
450  case WATCH_SOCK_UDP_SEND:
451  if(dhcp_alarm) alarm_set(10, dhcp_alarm_cb, 0);
452  dhcp_run_tick = wizpf_get_systick();
453  if(ret == RET_OK) {
454  DBG("DHCP Discovery Sent Async");
455  if(di.state == DHCP_STATE_INIT) SET_STATE(DHCP_STATE_SEARCHING);
456  else if(di.state == DHCP_STATE_SELECTING) SET_STATE(DHCP_STATE_REQUESTING);
457  else DBGCRTCA(TRUE, "wrong state(%d)", di.state);
458  } else {
459  DBGA("WATCH_SOCK_UDP_SEND fail - ret(%d)", ret);
460  }
461  break;
462  case WATCH_SOCK_TCP_SEND:
463  case WATCH_SOCK_CONN_TRY:
464  case WATCH_SOCK_CLS_TRY:
465  case WATCH_SOCK_CONN_EVT:
466  case WATCH_SOCK_CLS_EVT:
467  case WATCH_SOCK_RECV:
468  DBGCRTC(TRUE, "DHCP does not use TCP");
469  default: DBGCRTCA(TRUE, "wrong item(0x%x)", item);
470  }
471 
472 }
473 
474 static void dhcp_run(void)
475 {
476  static bool udp_open_fail = FALSE;
477 
478  if(di.state == DHCP_STATE_INIT && di.action != DHCP_ACT_START) {
479  DBG("wrong attempt");
480  return;
481  } else if(GetUDPSocketStatus(di.sock) == SOCKSTAT_CLOSED) {
482  if(udp_open_fail == TRUE && !IS_TIME_PASSED(dhcp_run_tick, DHCP_RETRY_DELAY))
483  goto RET_ALARM;
488  if(UDPOpen(di.sock, DHCP_CLIENT_PORT) == RET_OK) {
489  if(dhcp_async) sockwatch_open(di.sock, dhcp_async_cb);
490  udp_open_fail = FALSE;
491  dhcp_run_tick = wizpf_get_systick();
492  dhcp_run_cnt = 0;
493  } else {
494  ERR("UDPOpen fail");
495  udp_open_fail = TRUE;
496  dhcp_run_tick = wizpf_get_systick();
497  goto RET_ALARM;
498  }
499  }
500 
501  switch(di.state) {
502  case DHCP_STATE_INIT:
503  if(dhcp_run_cnt==0 && !IS_TIME_PASSED(dhcp_run_tick, DHCP_OPEN_DELAY))
504  goto RET_ALARM;
505 
506  if(dhcp_run_cnt < DHCP_SEND_RETRY_COUNT) {
507  dhcp_run_cnt++;
508  if(send_discover() == RET_OK) { // Discover ok
509  if(dhcp_async) {
510  DBG("DHCP Discovery Send Async");
512  return; // alarm set is not needed
513  } else {
514  DBG("DHCP Discovery Sent");
515  SET_STATE(DHCP_STATE_SEARCHING);
516  dhcp_run_tick = wizpf_get_systick();
517  }
518  } else {
519  ERRA("DHCP Discovery SEND fail - (%d)times", dhcp_run_cnt);
520  dhcp_run_tick = wizpf_get_systick();
521  }
522  } else {
523  ERRA("DHCP Discovery SEND fail - (%d)times", dhcp_run_cnt);
524  dhcp_run_cnt = 0;
525  UDPClose(di.sock);
526  if(dhcp_async) sockwatch_close(di.sock);
527  dhcp_fail();
528  return; // alarm set is not needed
529  }
530  break;
532  if(!IS_TIME_PASSED(dhcp_run_tick, DHCP_RETRY_DELAY)) {
533  int8 ret = recv_handler();
534  if(ret == DHCP_MSG_OFFER) {
535  SET_STATE(DHCP_STATE_SELECTING);
536  dhcp_run_tick = wizpf_get_systick();
537  dhcp_run_cnt = 0;
538  } else if(ret != RET_NOK) DBGCRTCA(TRUE, "recv wrong packet(%d)", ret);
539  } else {
540  ERRA("DHCP Offer RECV fail - for (%d)msec", DHCP_RETRY_DELAY);
541  SET_STATE(DHCP_STATE_INIT);
542  dhcp_run_tick = wizpf_get_systick();
543  }
544  break;
546  if(dhcp_run_cnt < DHCP_SEND_RETRY_COUNT) {
547  dhcp_run_cnt++;
548  if(send_request() == RET_OK) { // Request ok
549  if(dhcp_async) {
550  DBG("DHCP Request Send Async");
552  return; // alarm set is not needed
553  } else {
554  DBG("DHCP Request Sent");
555  SET_STATE(DHCP_STATE_REQUESTING);
556  dhcp_run_tick = wizpf_get_systick();
557  }
558  } else {
559  ERRA("DHCP Request SEND fail - (%d)times", dhcp_run_cnt);
560  dhcp_run_tick = wizpf_get_systick();
561  }
562  } else {
563  ERRA("DHCP Request SEND fail - (%d)times", dhcp_run_cnt);
564  dhcp_run_cnt = 0;
565  UDPClose(di.sock);
566  if(dhcp_async) sockwatch_close(di.sock);
567  dhcp_fail();
568  return; // alarm set is not needed
569  }
570  break;
572  if(!IS_TIME_PASSED(dhcp_run_tick, DHCP_RETRY_DELAY)) {
573  int8 ret = recv_handler();
574  if(ret == DHCP_MSG_ACK) { // Recv ACK
575  LOG("DHCP Success");
576  SET_STATE(DHCP_STATE_IP_CHECK);
577  dhcp_run_tick = wizpf_get_systick();
578  dhcp_run_cnt = 0;
579  } else if(ret == DHCP_MSG_NAK) { // Recv NAK
580  if(di.action == DHCP_ACT_START) {
581  SET_STATE(DHCP_STATE_INIT);
582  dhcp_run_tick = wizpf_get_systick();
583  } else {
584  SET_STATE(DHCP_STATE_BOUND);
585  }
586  dhcp_run_cnt = 0;
587  } else if(ret != RET_NOK) DBGCRTCA(TRUE, "recv wrong packet(%d)", ret);
588  } else {
589  ERRA("DHCP ACK RECV fail - for (%d)msec", DHCP_RETRY_DELAY);
590  if(di.action == DHCP_ACT_START) {
591  SET_STATE(DHCP_STATE_INIT);
592  dhcp_run_tick = wizpf_get_systick();
593  } else {
594  SET_STATE(DHCP_STATE_BOUND);
595  }
596  }
597  break;
598  case DHCP_STATE_IP_CHECK:
599  //if(send_checker() == RET_OK) {
600  SET_STATE(DHCP_STATE_BOUND);
601  SetNetInfo(&workinfo);
602  if(di.ip_update) di.ip_update();
603  LOGA("DHCP ok - New IP (%d.%d.%d.%d)",
604  workinfo.ip[0], workinfo.ip[1], workinfo.ip[2], workinfo.ip[3]);
605  //} else {
606  // SET_STATE(DHCP_STATE_INIT);
607  // ERR("IP Addr conflicted - IP(%d.%d.%d.%d)", workinfo.ip[0], workinfo.ip[1], workinfo.ip[2], workinfo.ip[3]);
608  // send_rel_dec(DHCP_MSG_DECLINE);
609  // if(di.ip_conflict) (*di.ip_conflict)();
610  //}
611  break;
612  case DHCP_STATE_BOUND:
613  di.action = DHCP_ACT_NONE;
614  UDPClose(di.sock);
615  if(dhcp_async) sockwatch_close(di.sock);
616  return; // alarm set is not needed
617  case DHCP_STATE_FAILED:
618  return; // alarm set is not needed
619  default:
620  ERRA("wrong state(%d)", di.state);
621  return; // alarm set is not needed
622  }
623 
624 RET_ALARM:
625  if(dhcp_alarm) alarm_set(10, dhcp_alarm_cb, 0);
626 }
627 
628 static void dhcp_fail(void)
629 {
630  LOG("DHCP Fail - set temp addr");
631  di.action = DHCP_ACT_NONE;
632  SET_STATE(DHCP_STATE_FAILED);
633  memcpy(&workinfo, &storage, sizeof(storage));
634  memset(workinfo.mac, 0, 6);
635  SetNetInfo(&workinfo);
636  network_disp(NULL);
637  if(dhcp_alarm)
638  alarm_set(DHCP_START_RETRY_DELAY, dhcp_alarm_cb, 0);
639  //send_checker_NB();
640 }
641 
642 static int8 recv_handler(void)
643 {
644  uint8 *cur, *end;
645  uint8 recv_ip[4], opt_len, msg_type;
646  int32 recv_len;
647  uint16 recv_port;
648 
649  recv_len = GetSocketRxRecvBufferSize(di.sock);
650  if(recv_len == 0) return RET_NOK;
651  else memset(&dm, 0, sizeof(struct dhcp_msg));
652 
653  recv_len = UDPRecv(di.sock, (int8*)&dm, sizeof(struct dhcp_msg), recv_ip, &recv_port);
654  if(recv_len < 0) {
655  ERRA("UDPRecv fail - ret(%d)", recv_len);
656  return RET_NOK;
657  }
658 
659  //DBGFUNC(print_dump(&dm, sizeof(dm))); // For debugging received packet
660  DBGA("DHCP_SIP:%d.%d.%d.%d",di.srv_ip[0],di.srv_ip[1],di.srv_ip[2],di.srv_ip[3]);
661  DBGA("DHCP_RIP:%d.%d.%d.%d",di.srv_ip_real[0],di.srv_ip_real[1],di.srv_ip_real[2],di.srv_ip_real[3]);
662  DBGA("recv_ip:%d.%d.%d.%d",recv_ip[0],recv_ip[1],recv_ip[2],recv_ip[3]);
663 
664  if(dm.op != DHCP_BOOTREPLY || recv_port != DHCP_SERVER_PORT) {
665  if(dm.op != DHCP_BOOTREPLY) DBG("DHCP : NO DHCP MSG");
666  if(recv_port != DHCP_SERVER_PORT) DBG("DHCP : WRONG PORT");
667  return RET_NOK;
668  }
669 
670  if(memcmp(dm.chaddr, storage.mac, 6) != 0 || dm.xid != htonl(di.xid)) {
671  DBG("No My DHCP Message. This message is ignored.");
672  DBGA("SRC_MAC_ADDR(%02X:%02X:%02X:%02X:%02X:%02X)",
673  storage.mac[0], storage.mac[1], storage.mac[2],
674  storage.mac[3], storage.mac[4], storage.mac[5]);
675  DBGA("chaddr(%02X:%02X:%02X:%02X:%02X:%02X)", dm.chaddr[0],
676  dm.chaddr[1], dm.chaddr[2], dm.chaddr[3], dm.chaddr[4], dm.chaddr[5]);
677  DBGA("DHCP_XID(%08lX), xid(%08lX), yiaddr(%d.%d.%d.%d)", htonl(di.xid),
678  dm.xid, dm.yiaddr[0], dm.yiaddr[1], dm.yiaddr[2], dm.yiaddr[3]);
679  return RET_NOK;
680  }
681 
682  if( *((uint32*)di.srv_ip) != 0x00000000 ) {
683  if( *((uint32*)di.srv_ip_real) != *((uint32*)recv_ip) &&
684  *((uint32*)di.srv_ip) != *((uint32*)recv_ip) ) {
685  DBG("Another DHCP sever send a response message. This is ignored.");
686  DBGA("IP:%d.%d.%d.%d",recv_ip[0],recv_ip[1],recv_ip[2],recv_ip[3]);
687  return RET_NOK;
688  }
689  }
690 
691  memcpy(workinfo.ip, dm.yiaddr, 4);
692  DBG("DHCP MSG received..");
693  DBGA("yiaddr : %d.%d.%d.%d",workinfo.ip[0],workinfo.ip[1],workinfo.ip[2],workinfo.ip[3]);
694 
695  msg_type = 0;
696  cur = (uint8 *)(&dm.op);
697  cur = cur + 240;
698  end = cur + (recv_len - 240); //printf("cur : 0x%08X end : 0x%08X recv_len : %d\r\n", cur, end, recv_len);
699  while ( cur < end )
700  {
701  switch ( *cur++ )
702  {
703  case padOption:
704  break;
705  case endOption:
706  return msg_type;
707  case dhcpMessageType:
708  opt_len = *cur++;
709  msg_type = *cur;
710  DBGA("dhcpMessageType : %x", msg_type);
711  break;
712  case subnetMask:
713  opt_len =* cur++;
714  memcpy(workinfo.sn,cur,4);
715  DBGA("subnetMask : %d.%d.%d.%d",
716  workinfo.sn[0],workinfo.sn[1],workinfo.sn[2],workinfo.sn[3]);
717  break;
718  case routersOnSubnet:
719  opt_len = *cur++;
720  memcpy(workinfo.gw,cur,4);
721  DBGA("routersOnSubnet : %d.%d.%d.%d",
722  workinfo.gw[0],workinfo.gw[1],workinfo.gw[2],workinfo.gw[3]);
723  break;
724  case dns:
725  opt_len = *cur++;
726  memcpy(workinfo.dns,cur,4);
727  break;
728  case dhcpIPaddrLeaseTime:
729  opt_len = *cur++;
730  di.lease_time = ntohl(*((uint32*)cur));
731  di.renew_time = di.lease_time / 2; // 0.5
732  di.rebind_time = di.lease_time / 8 * 7; // 0.875
733  DBGA("lease(%d), renew(%d), rebind(%d)", di.lease_time, di.renew_time, di.rebind_time);
734  break;
735  case dhcpServerIdentifier:
736  opt_len = *cur++;
737  DBGA("DHCP_SIP : %d.%d.%d.%d", di.srv_ip[0], di.srv_ip[1], di.srv_ip[2], di.srv_ip[3]);
738  if( *((uint32*)di.srv_ip) == 0 || *((uint32*)di.srv_ip_real) == *((uint32*)recv_ip) ||
739  *((uint32*)di.srv_ip) == *((uint32*)recv_ip) ) {
740  memcpy(di.srv_ip,cur,4);
741  memcpy(di.srv_ip_real,recv_ip,4); // Copy the real ip address of my DHCP server
742  DBGA("My dhcpServerIdentifier : %d.%d.%d.%d",
743  di.srv_ip[0], di.srv_ip[1], di.srv_ip[2], di.srv_ip[3]);
744  DBGA("My DHCP server real IP address : %d.%d.%d.%d",
745  di.srv_ip_real[0], di.srv_ip_real[1], di.srv_ip_real[2], di.srv_ip_real[3]);
746  } else {
747  DBGA("Another dhcpServerIdentifier : MY(%d.%d.%d.%d)",
748  di.srv_ip[0], di.srv_ip[1], di.srv_ip[2], di.srv_ip[3]);
749  DBGA("Another(%d.%d.%d.%d)", recv_ip[0], recv_ip[1], recv_ip[2], recv_ip[3]);
750  }
751  break;
752  default:
753  opt_len = *cur++;
754  DBGA("opt_len : %d", opt_len);
755  break;
756  } // switch
757  cur+=opt_len;
758  } // while
759 
760  return RET_NOK;
761 }
762 
763 static int8 send_discover(void)
764 {
765  uint8 srv_ip[4];
766  int32 len = 0;
767 
768  memset(&dm, 0, sizeof(struct dhcp_msg));
769 
770  *((uint32*)di.srv_ip)=0;
771  *((uint32*)di.srv_ip_real)=0;
772 
773  dm.op = DHCP_BOOTREQUEST;
774  dm.htype = DHCP_HTYPE10MB;
775  dm.hlen = DHCP_HLENETHERNET;
776  dm.hops = DHCP_HOPS;
777  dm.xid = htonl(di.xid);
778  dm.secs = htons(DHCP_SECS);
779  memcpy(dm.chaddr, storage.mac, 6);
780  dm.flags = htons(DHCP_BROADCAST);
781 
782  // MAGIC_COOKIE
783  *(uint32*)&dm.opt[len] = htonl(MAGIC_COOKIE);
784  len += 4;
785 
786  // Option Request Param.
787  dm.opt[len++] = dhcpMessageType;
788  dm.opt[len++] = 0x01;
789  dm.opt[len++] = DHCP_MSG_DISCOVER;
790 
791  // Client identifier
792  dm.opt[len++] = dhcpClientIdentifier;
793  dm.opt[len++] = 0x07;
794  dm.opt[len++] = 0x01;
795  memcpy(&dm.opt[len], storage.mac, 6);
796  len += 6;
797 
798  // host name
799  dm.opt[len++] = hostName;
800  dm.opt[len++] = strlen(HOST_NAME) + 6; // length of hostname + 3
801  strcpy((char*)&dm.opt[len], HOST_NAME);
802  len += strlen(HOST_NAME);
803  sprintf((char*)&dm.opt[len], "%02x%02x%02x",
804  storage.mac[3], storage.mac[4], storage.mac[5]);
805  len += 6;
806 
807  dm.opt[len++] = dhcpParamRequest;
808  dm.opt[len++] = 0x06;
809  dm.opt[len++] = subnetMask;
810  dm.opt[len++] = routersOnSubnet;
811  dm.opt[len++] = dns;
812  dm.opt[len++] = domainName;
813  dm.opt[len++] = dhcpT1value;
814  dm.opt[len++] = dhcpT2value;
815  dm.opt[len++] = endOption;
816 
817  // send broadcasting packet
818  srv_ip[0] = srv_ip[1] = srv_ip[2] = srv_ip[3] = 255;
819 
820  if(dhcp_async) {
821  len = UDPSendNB(di.sock, (int8*)&dm, sizeof(struct dhcp_msg), srv_ip, DHCP_SERVER_PORT);
822  if(len < sizeof(struct dhcp_msg)) {
823  if(len < 0) ERRA("UDPSend fail - ret(%d)", len);
824  else ERRA("UDPSend sent less than size - size(%d), sent(%d)",
825  sizeof(struct dhcp_msg), len);
826  return RET_NOK;
827  } else sockwatch_set(di.sock, WATCH_SOCK_UDP_SEND);
828  } else {
829  len = UDPSend(di.sock, (int8*)&dm, sizeof(struct dhcp_msg), srv_ip, DHCP_SERVER_PORT);
830  if(len <= 0) {
831  ERRA("UDPSend fail - ret(%d)", len);
832  return RET_NOK;
833  }
834  }
835 
836  return RET_OK;
837 }
838 
839 static int8 send_request(void)
840 {
841  uint8 srv_ip[4];
842  int32 len = 0;
843 
844  memset(&dm, 0, sizeof(struct dhcp_msg));
845 
846  dm.op = DHCP_BOOTREQUEST;
847  dm.htype = DHCP_HTYPE10MB;
848  dm.hlen = DHCP_HLENETHERNET;
849  dm.hops = DHCP_HOPS;
850  dm.xid = htonl(di.xid);
851  dm.secs = htons(DHCP_SECS);
852 
853  if(di.action == DHCP_ACT_RENEW) {
854  dm.flags = 0; // For Unicast
855  memcpy(dm.ciaddr, workinfo.ip, 4);
856  } else {
857  dm.flags = htons(DHCP_BROADCAST);
858  }
859 
860  memcpy(dm.chaddr, storage.mac, 6);
861 
862  // MAGIC_COOKIE
863  *(uint32*)&dm.opt[len] = htonl(MAGIC_COOKIE);
864  len += 4;
865 
866  // Option Request Param.
867  dm.opt[len++] = dhcpMessageType;
868  dm.opt[len++] = 0x01;
869  dm.opt[len++] = DHCP_MSG_REQUEST;
870 
871  dm.opt[len++] = dhcpClientIdentifier;
872  dm.opt[len++] = 0x07;
873  dm.opt[len++] = 0x01;
874  memcpy(&dm.opt[len], storage.mac, 6);
875  len += 6;
876 
877  if(di.action != DHCP_ACT_RENEW) {
878  dm.opt[len++] = dhcpRequestedIPaddr;
879  dm.opt[len++] = 0x04;
880  memcpy(&dm.opt[len], workinfo.ip, 4);
881  len += 4;
882  dm.opt[len++] = dhcpServerIdentifier;
883  dm.opt[len++] = 0x04;
884  memcpy(&dm.opt[len], di.srv_ip, 4);
885  len += 4;
886  }
887 
888  // host name
889  dm.opt[len++] = hostName;
890  dm.opt[len++] = strlen(HOST_NAME) + 6; // length of hostname + 3
891  strcpy((char*)&dm.opt[len], HOST_NAME);
892  len += strlen(HOST_NAME);
893  sprintf((char*)&dm.opt[len], "%02x%02x%02x",
894  storage.mac[3], storage.mac[4], storage.mac[5]);
895  len += 6;
896 
897  dm.opt[len++] = dhcpParamRequest;
898  dm.opt[len++] = 0x08;
899  dm.opt[len++] = subnetMask;
900  dm.opt[len++] = routersOnSubnet;
901  dm.opt[len++] = dns;
902  dm.opt[len++] = domainName;
903  dm.opt[len++] = dhcpT1value;
904  dm.opt[len++] = dhcpT2value;
905  dm.opt[len++] = performRouterDiscovery;
906  dm.opt[len++] = staticRoute;
907  dm.opt[len++] = endOption;
908 
909  // send broadcasting packet
910  if(di.action == DHCP_ACT_RENEW) {
911  memcpy(srv_ip, di.srv_ip, 4);
912  } else {
913  srv_ip[0] = srv_ip[1] = srv_ip[2] = srv_ip[3] = 255;
914  }
915 
916  if(dhcp_async) {
917  len = UDPSendNB(di.sock, (int8*)&dm, sizeof(struct dhcp_msg), srv_ip, DHCP_SERVER_PORT);
918  if(len < sizeof(struct dhcp_msg)) {
919  if(len < 0) ERRA("UDPSend fail - ret(%d)", len);
920  else ERRA("UDPSend sent less than size - size(%d), sent(%d)", sizeof(struct dhcp_msg), len);
921  return RET_NOK;
922  } else sockwatch_set(di.sock, WATCH_SOCK_UDP_SEND);
923  } else {
924  len = UDPSend(di.sock, (int8*)&dm, sizeof(struct dhcp_msg), srv_ip, DHCP_SERVER_PORT);
925  if(len <= 0) {
926  ERRA("UDPSend fail - ret(%d)", len);
927  return RET_NOK;
928  }
929  }
930 
931  return RET_OK;
932 }
933 
934 /*
935 static int8 send_rel_dec(int8 msgtype)
936 {
937  int32 len =0;
938  uint8 srv_ip[4];
939 
940  memset(&dm, 0, sizeof(struct dhcp_msg));
941 
942  dm.op = DHCP_BOOTREQUEST;
943  dm.htype = DHCP_HTYPE10MB;
944  dm.hlen = DHCP_HLENETHERNET;
945  dm.hops = DHCP_HOPS;
946  dm.xid = htonl(di.xid);
947  dm.secs = htons(DHCP_SECS);
948  dm.flags = DHCP_UNICAST; //DHCP_BROADCAST;
949  memcpy(dm.chaddr, storage.mac, 6);
950 
951  // MAGIC_COOKIE
952  *(uint32*)&dm.opt[len] = htonl(MAGIC_COOKIE);
953  len += 4;
954 
955  // Option Request Param.
956  dm.opt[len++] = dhcpMessageType;
957  dm.opt[len++] = 0x01;
958  if(msgtype == DHCP_MSG_DECLINE) dm.opt[len++] = DHCP_MSG_DECLINE;
959  else dm.opt[len++] = DHCP_MSG_RELEASE;
960 
961  dm.opt[len++] = dhcpClientIdentifier;
962  dm.opt[len++] = 0x07;
963  dm.opt[len++] = 0x01;
964  memcpy(&dm.opt[len], storage.mac, 6);
965  len += 6;
966 
967  dm.opt[len++] = dhcpServerIdentifier;
968  dm.opt[len++] = 0x04;
969  memcpy(&dm.opt[len], di.srv_ip, 4);
970  len += 4;
971 
972  if(msgtype == DHCP_MSG_DECLINE) {
973  dm.opt[len++] = dhcpRequestedIPaddr;
974  dm.opt[len++] = 0x04;
975  memcpy(&dm.opt[len], workinfo.ip, 4);
976  len += 4;
977  dm.opt[len++] = endOption;
978  srv_ip[0] = srv_ip[1] = srv_ip[2] = srv_ip[3] = 255;
979  } else {
980  dm.opt[len++] = endOption;
981  memcpy(srv_ip, di.srv_ip, 4);
982  }
983 
984  if(dhcp_async) {
985  len = UDPSendNB(di.sock, (int8*)&dm, sizeof(struct dhcp_msg), srv_ip, DHCP_SERVER_PORT);
986  if(len < sizeof(struct dhcp_msg)) {
987  if(len < 0) ERRA("UDPSend fail - ret(%d)", len);
988  else ERRA("UDPSend sent less than size - size(%d), sent(%d)", sizeof(struct dhcp_msg), len);
989  return RET_NOK;
990  } else sockwatch_set(di.sock, WATCH_SOCK_UDP_SEND);
991  } else {
992  len = UDPSend(di.sock, (int8*)&dm, sizeof(struct dhcp_msg), srv_ip, DHCP_SERVER_PORT);
993  if(len <= 0) {
994  ERRA("UDPSend fail - ret(%d)", len);
995  return RET_NOK;
996  }
997  }
998 
999  return RET_OK;
1000 }
1001 */
1002 
1003 /*
1004 static int8 send_checker(void)
1005 {
1006  int16 len;
1007 
1008  if(dhcp_async) {
1009  len = UDPSendNB(di.sock, "CHECK_IP_CONFLICT", 17, workinfo.ip, 5000);
1010  if(len < sizeof(struct dhcp_msg)) {
1011  if(len < 0) ERRA("UDPSend fail - ret(%d)", len);
1012  else ERRA("UDPSend sent less than size - size(%d), sent(%d)", 17, len);
1013  return RET_NOK;
1014  } else sockwatch_set(di.sock, WATCH_SOCK_UDP_SEND);
1015  } else {
1016  len = UDPSend(di.sock, "CHECK_IP_CONFLICT", 17, workinfo.ip, 5000);
1017  if(len > 0) { // sendto is complete. that means there is a node which has a same IP.
1018  ERR("IP Conflict");
1019  return RET_NOK;
1020  }
1021  }
1022 
1023  return RET_OK;
1024 }
1025 
1026 static int8 send_checker_NB(void)
1027 {
1028  // Todo
1029  return RET_OK;
1030 }
1031 */
1032 //static void default_ip_update(void){}
1033 //static void default_ip_conflict(void){}
1034 
1035 
1036 
1037