00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077 #include "lwip/stats.h"
00078 #include "lwip/mem.h"
00079 #include "lwip/udp.h"
00080 #include "lwip/netif.h"
00081 #include "lwip/inet.h"
00082 #include "lwip/ip_addr.h"
00083 #include "netif/etharp.h"
00084
00085 #include "lwip/sys.h"
00086 #include "lwip/opt.h"
00087 #include "lwip/dhcp.h"
00088
00091 static u32_t xid = 0xABCD0000;
00092
00094 static void dhcp_handle_ack(struct netif *netif);
00095 static void dhcp_handle_nak(struct netif *netif);
00096 static void dhcp_handle_offer(struct netif *netif);
00097
00098 static err_t dhcp_discover(struct netif *netif);
00099 static err_t dhcp_select(struct netif *netif);
00100 static void dhcp_check(struct netif *netif);
00101 static void dhcp_bind(struct netif *netif);
00102 static err_t dhcp_decline(struct netif *netif);
00103 static err_t dhcp_rebind(struct netif *netif);
00104 static err_t dhcp_release(struct netif *netif);
00105 static void dhcp_set_state(struct dhcp *dhcp, unsigned char new_state);
00106
00108 static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u16_t port);
00109 static err_t dhcp_unfold_reply(struct dhcp *dhcp);
00110 static u8_t *dhcp_get_option_ptr(struct dhcp *dhcp, u8_t option_type);
00111 static u8_t dhcp_get_option_byte(u8_t *ptr);
00112 static u16_t dhcp_get_option_short(u8_t *ptr);
00113 static u32_t dhcp_get_option_long(u8_t *ptr);
00114 static void dhcp_free_reply(struct dhcp *dhcp);
00115
00117 static void dhcp_timeout(struct netif *netif);
00118 static void dhcp_t1_timeout(struct netif *netif);
00119 static void dhcp_t2_timeout(struct netif *netif);
00120
00123 static err_t dhcp_create_request(struct netif *netif);
00125 static void dhcp_delete_request(struct netif *netif);
00127 static void dhcp_option(struct dhcp *dhcp, u8_t option_type, u8_t option_len);
00129 static void dhcp_option_byte(struct dhcp *dhcp, u8_t value);
00130 static void dhcp_option_short(struct dhcp *dhcp, u16_t value);
00131 static void dhcp_option_long(struct dhcp *dhcp, u32_t value);
00133 static void dhcp_option_trailer(struct dhcp *dhcp);
00134
00146 static void dhcp_handle_nak(struct netif *netif) {
00147 struct dhcp *dhcp = netif->dhcp;
00148 u16_t msecs = 10 * 1000;
00149 DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_handle_nak()\n"));
00150 dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
00151 DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_handle_nak(): set request timeout %u msecs\n", msecs));
00152 dhcp_set_state(dhcp, DHCP_BACKING_OFF);
00153 }
00154
00162 static void dhcp_check(struct netif *netif)
00163 {
00164 struct dhcp *dhcp = netif->dhcp;
00165 err_t result;
00166 u16_t msecs;
00167 DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_check()\n"));
00168
00169
00170 result = etharp_query(netif, &dhcp->offered_ip_addr, NULL);
00171 if (result != ERR_OK) {
00172 DEBUGF(DHCP_DEBUG | DBG_TRACE | 2, ("dhcp_check: could not perform ARP query\n"));
00173 }
00174 dhcp->tries++;
00175 msecs = 500;
00176 dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
00177 DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_check(): set request timeout %u msecs\n", msecs));
00178 dhcp_set_state(dhcp, DHCP_CHECKING);
00179 }
00180
00186 static void dhcp_handle_offer(struct netif *netif)
00187 {
00188 struct dhcp *dhcp = netif->dhcp;
00189
00190 u8_t *option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_SERVER_ID);
00191 if (option_ptr != NULL)
00192 {
00193 dhcp->server_ip_addr.addr = htonl(dhcp_get_option_long(&option_ptr[2]));
00194 DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_handle_offer(): server 0x%08lx\n", dhcp->server_ip_addr.addr));
00195
00196 ip_addr_set(&dhcp->offered_ip_addr, (struct ip_addr *)&dhcp->msg_in->yiaddr);
00197 DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_handle_offer(): offer for 0x%08lx\n", dhcp->offered_ip_addr.addr));
00198 dhcp_select(netif);
00199 }
00200 }
00201
00210 static err_t dhcp_select(struct netif *netif)
00211 {
00212 struct dhcp *dhcp = netif->dhcp;
00213 err_t result;
00214 u32_t msecs;
00215 DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_select()\n"));
00216
00217
00218 result = dhcp_create_request(netif);
00219 if (result == ERR_OK)
00220 {
00221 dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN);
00222 dhcp_option_byte(dhcp, DHCP_REQUEST);
00223
00224 dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
00225 dhcp_option_short(dhcp, 576);
00226
00227
00228 dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4);
00229 dhcp_option_long(dhcp, ntohl(dhcp->offered_ip_addr.addr));
00230
00231 dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4);
00232 dhcp_option_long(dhcp, ntohl(dhcp->server_ip_addr.addr));
00233
00234 dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, 3);
00235 dhcp_option_byte(dhcp, DHCP_OPTION_SUBNET_MASK);
00236 dhcp_option_byte(dhcp, DHCP_OPTION_ROUTER);
00237 dhcp_option_byte(dhcp, DHCP_OPTION_BROADCAST);
00238
00239 dhcp_option_trailer(dhcp);
00240
00241 pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
00242
00243
00244
00245 udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
00246
00247 udp_connect(dhcp->pcb, IP_ADDR_BROADCAST, DHCP_SERVER_PORT);
00248 udp_send(dhcp->pcb, dhcp->p_out);
00249
00250 udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);
00251 dhcp_delete_request(netif);
00252 DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_select: REQUESTING\n"));
00253 dhcp_set_state(dhcp, DHCP_REQUESTING);
00254 } else {
00255 DEBUGF(DHCP_DEBUG | DBG_TRACE | 2, ("dhcp_select: could not allocate DHCP request\n"));
00256 }
00257 dhcp->tries++;
00258 msecs = dhcp->tries < 4 ? dhcp->tries * 1000 : 4 * 1000;
00259 dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
00260 DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_select(): set request timeout %u msecs\n", msecs));
00261 return result;
00262 }
00263
00268 void dhcp_coarse_tmr()
00269 {
00270 struct netif *netif = netif_list;
00271 DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_coarse_tmr()\n"));
00272
00273 while (netif != NULL) {
00274
00275 if (netif->dhcp != NULL) {
00276
00277 if (netif->dhcp->t2_timeout-- == 1) {
00278 DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_coarse_tmr(): t2 timeout\n"));
00279
00280 dhcp_t2_timeout(netif);
00281
00282 } else if (netif->dhcp->t1_timeout-- == 1) {
00283 DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_coarse_tmr(): t1 timeout\n"));
00284
00285 dhcp_t1_timeout(netif);
00286 }
00287 }
00288
00289 netif = netif->next;
00290 }
00291 }
00292
00299 void dhcp_fine_tmr()
00300 {
00301 struct netif *netif = netif_list;
00302
00303 while (netif != NULL) {
00304
00305 if (netif->dhcp != NULL) {
00306
00307 if (netif->dhcp->request_timeout-- == 1) {
00308 DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_fine_tmr(): request timeout\n"));
00309
00310 dhcp_timeout(netif);
00311 }
00312 }
00313
00314 netif = netif->next;
00315 }
00316 }
00317
00327 static void dhcp_timeout(struct netif *netif)
00328 {
00329 struct dhcp *dhcp = netif->dhcp;
00330 DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_timeout()\n"));
00331
00332 if ((dhcp->state == DHCP_BACKING_OFF) || (dhcp->state == DHCP_SELECTING)) {
00333 DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_timeout(): restarting discovery\n"));
00334 dhcp_discover(netif);
00335
00336 } else if (dhcp->state == DHCP_REQUESTING) {
00337 DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_timeout(): REQUESTING, DHCP request timed out\n"));
00338 if (dhcp->tries <= 5) {
00339 dhcp_select(netif);
00340 } else {
00341 DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_timeout(): REQUESTING, releasing, restarting\n"));
00342 dhcp_release(netif);
00343 dhcp_discover(netif);
00344 }
00345
00346 } else if (dhcp->state == DHCP_CHECKING) {
00347 DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_timeout(): CHECKING, ARP request timed out\n"));
00348 if (dhcp->tries <= 1) {
00349 dhcp_check(netif);
00350
00351
00352 } else {
00353
00354 dhcp_bind(netif);
00355 }
00356 }
00357
00358 else if (dhcp->state == DHCP_RENEWING) {
00359 DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_timeout(): RENEWING, DHCP request timed out\n"));
00360
00361
00362 dhcp_renew(netif);
00363
00364 } else if (dhcp->state == DHCP_REBINDING) {
00365 DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_timeout(): REBINDING, DHCP request timed out\n"));
00366 if (dhcp->tries <= 8) {
00367 dhcp_rebind(netif);
00368 } else {
00369 DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_timeout(): RELEASING, DISCOVERING\n"));
00370 dhcp_release(netif);
00371 dhcp_discover(netif);
00372 }
00373 }
00374 }
00375
00381 static void dhcp_t1_timeout(struct netif *netif)
00382 {
00383 struct dhcp *dhcp = netif->dhcp;
00384 DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_t1_timeout()\n"));
00385 if ((dhcp->state == DHCP_REQUESTING) || (dhcp->state == DHCP_BOUND) || (dhcp->state == DHCP_RENEWING)) {
00386
00387
00388 DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_t1_timeout(): must renew\n"));
00389 dhcp_renew(netif);
00390 }
00391 }
00392
00397 static void dhcp_t2_timeout(struct netif *netif)
00398 {
00399 struct dhcp *dhcp = netif->dhcp;
00400 DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_t2_timeout()\n"));
00401 if ((dhcp->state == DHCP_REQUESTING) || (dhcp->state == DHCP_BOUND) || (dhcp->state == DHCP_RENEWING)) {
00402
00403 DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_t2_timeout(): must rebind\n"));
00404 dhcp_rebind(netif);
00405 }
00406 }
00407
00413 static void dhcp_handle_ack(struct netif *netif)
00414 {
00415 struct dhcp *dhcp = netif->dhcp;
00416 u8_t *option_ptr;
00417
00418 dhcp->offered_sn_mask.addr = 0;
00419 dhcp->offered_gw_addr.addr = 0;
00420 dhcp->offered_bc_addr.addr = 0;
00421
00422
00423 option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_LEASE_TIME);
00424 if (option_ptr != NULL) {
00425
00426 dhcp->offered_t0_lease = dhcp_get_option_long(option_ptr + 2);
00427 }
00428
00429 option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_T1);
00430 if (option_ptr != NULL) {
00431
00432 dhcp->offered_t1_renew = dhcp_get_option_long(option_ptr + 2);
00433 } else {
00434
00435 dhcp->offered_t1_renew = dhcp->offered_t0_lease / 2;
00436 }
00437
00438
00439 option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_T2);
00440 if (option_ptr != NULL) {
00441
00442 dhcp->offered_t2_rebind = dhcp_get_option_long(option_ptr + 2);
00443 } else {
00444
00445 dhcp->offered_t2_rebind = dhcp->offered_t0_lease;
00446 }
00447
00448
00449 ip_addr_set(&dhcp->offered_ip_addr, &dhcp->msg_in->yiaddr);
00450
00451
00452 option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_SUBNET_MASK);
00453
00454 if (option_ptr != NULL) {
00455 dhcp->offered_sn_mask.addr = htonl(dhcp_get_option_long(&option_ptr[2]));
00456 }
00457
00458
00459 option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_ROUTER);
00460 if (option_ptr != NULL) {
00461 dhcp->offered_gw_addr.addr = htonl(dhcp_get_option_long(&option_ptr[2]));
00462 }
00463
00464
00465 option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_BROADCAST);
00466 if (option_ptr != NULL) {
00467 dhcp->offered_bc_addr.addr = htonl(dhcp_get_option_long(&option_ptr[2]));
00468 }
00469 }
00470
00484 err_t dhcp_start(struct netif *netif)
00485 {
00486 struct dhcp *dhcp = netif->dhcp;
00487 err_t result = ERR_OK;
00488
00489 LWIP_ASSERT("netif != NULL", netif != NULL);
00490 DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_start(netif=%p) %c%c%u\n", netif, netif->name[0], netif->name[1], netif->num));
00491
00492 if (dhcp == NULL) {
00493 DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_start(): starting new DHCP client\n"));
00494 dhcp = mem_malloc(sizeof(struct dhcp));
00495 if (dhcp == NULL) {
00496 DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_start(): could not allocate dhcp\n"));
00497 netif->flags &= ~NETIF_FLAG_DHCP;
00498 return ERR_MEM;
00499 }
00500
00501 memset(dhcp, 0, sizeof(struct dhcp));
00502 DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_start(): allocated dhcp"));
00503 dhcp->pcb = udp_new();
00504 if (dhcp->pcb == NULL) {
00505 DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_start(): could not obtain pcb\n"));
00506 mem_free((void *)dhcp);
00507 dhcp = NULL;
00508 netif->flags &= ~NETIF_FLAG_DHCP;
00509 return ERR_MEM;
00510 }
00511
00512 netif->dhcp = dhcp;
00513 DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_start(): created new udp pcb\n"));
00514 DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_start(): starting DHCP configuration\n"));
00515 } else {
00516 DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE | 3, ("dhcp_start(): restarting DHCP configuration\n"));
00517 }
00518
00519 result = dhcp_discover(netif);
00520 if (result != ERR_OK) {
00521
00522 dhcp_stop(netif);
00523 }
00524 return result;
00525 }
00526
00537 void dhcp_inform(struct netif *netif)
00538 {
00539 struct dhcp *dhcp;
00540 err_t result = ERR_OK;
00541 dhcp = mem_malloc(sizeof(struct dhcp));
00542 if (dhcp == NULL) {
00543 DEBUGF(DHCP_DEBUG | DBG_TRACE | 2, ("dhcp_inform(): could not allocate dhcp\n"));
00544 return;
00545 }
00546 memset(dhcp, 0, sizeof(struct dhcp));
00547
00548 DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_inform(): allocated dhcp\n"));
00549 dhcp->pcb = udp_new();
00550 if (dhcp->pcb == NULL) {
00551 DEBUGF(DHCP_DEBUG | DBG_TRACE | 2, ("dhcp_inform(): could not obtain pcb"));
00552 mem_free((void *)dhcp);
00553 return;
00554 }
00555 DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_inform(): created new udp pcb\n"));
00556
00557 result = dhcp_create_request(netif);
00558 if (result == ERR_OK) {
00559
00560 dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN);
00561 dhcp_option_byte(dhcp, DHCP_INFORM);
00562
00563 dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
00564
00565 dhcp_option_short(dhcp, 576);
00566
00567 dhcp_option_trailer(dhcp);
00568
00569 pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
00570
00571 udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
00572 udp_connect(dhcp->pcb, IP_ADDR_BROADCAST, DHCP_SERVER_PORT);
00573 DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_inform: INFORMING\n"));
00574 udp_send(dhcp->pcb, dhcp->p_out);
00575 udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);
00576 dhcp_delete_request(netif);
00577 } else {
00578 DEBUGF(DHCP_DEBUG | DBG_TRACE | 2, ("dhcp_inform: could not allocate DHCP request\n"));
00579 }
00580
00581 if (dhcp != NULL)
00582 {
00583 if (dhcp->pcb != NULL) udp_remove(dhcp->pcb);
00584 dhcp->pcb = NULL;
00585 mem_free((void *)dhcp);
00586 }
00587 }
00588
00589 #if DHCP_DOES_ARP_CHECK
00590
00596 void dhcp_arp_reply(struct netif *netif, struct ip_addr *addr)
00597 {
00598 DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_arp_reply()\n"));
00599
00600 if ((netif->dhcp != NULL) && (netif->dhcp->state == DHCP_CHECKING)) {
00601 DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_arp_reply(): CHECKING, arp reply for 0x%08lx\n", addr->addr));
00602
00603
00604 if (ip_addr_cmp(addr, &netif->dhcp->offered_ip_addr)) {
00605
00606 DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE | 1, ("dhcp_arp_reply(): arp reply matched with offered address, declining\n"));
00607 dhcp_decline(netif);
00608 }
00609 }
00610 }
00611
00619 static err_t dhcp_decline(struct netif *netif)
00620 {
00621 struct dhcp *dhcp = netif->dhcp;
00622 err_t result = ERR_OK;
00623 u16_t msecs;
00624 DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_decline()\n"));
00625 dhcp_set_state(dhcp, DHCP_BACKING_OFF);
00626
00627 result = dhcp_create_request(netif);
00628 if (result == ERR_OK)
00629 {
00630 dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN);
00631 dhcp_option_byte(dhcp, DHCP_DECLINE);
00632
00633 dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
00634 dhcp_option_short(dhcp, 576);
00635
00636 dhcp_option_trailer(dhcp);
00637
00638 pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
00639
00640 udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
00641 udp_connect(dhcp->pcb, &dhcp->server_ip_addr, DHCP_SERVER_PORT);
00642 udp_send(dhcp->pcb, dhcp->p_out);
00643 dhcp_delete_request(netif);
00644 DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_decline: BACKING OFF\n"));
00645 } else {
00646 DEBUGF(DHCP_DEBUG | DBG_TRACE | 2, ("dhcp_decline: could not allocate DHCP request\n"));
00647 }
00648 dhcp->tries++;
00649 msecs = 10*1000;
00650 dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
00651 DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_decline(): set request timeout %u msecs\n", msecs));
00652 return result;
00653 }
00654 #endif
00655
00656
00661 static err_t dhcp_discover(struct netif *netif)
00662 {
00663 struct dhcp *dhcp = netif->dhcp;
00664 err_t result = ERR_OK;
00665 u16_t msecs;
00666 DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_discover()\n"));
00667 ip_addr_set(&dhcp->offered_ip_addr, IP_ADDR_ANY);
00668
00669 result = dhcp_create_request(netif);
00670 if (result == ERR_OK)
00671 {
00672 DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_discover: making request\n"));
00673 dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN);
00674 dhcp_option_byte(dhcp, DHCP_DISCOVER);
00675
00676 dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
00677 dhcp_option_short(dhcp, 576);
00678
00679 dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, 3);
00680 dhcp_option_byte(dhcp, DHCP_OPTION_SUBNET_MASK);
00681 dhcp_option_byte(dhcp, DHCP_OPTION_ROUTER);
00682 dhcp_option_byte(dhcp, DHCP_OPTION_BROADCAST);
00683
00684 dhcp_option_trailer(dhcp);
00685
00686 DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_discover: realloc()ing\n"));
00687 pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
00688
00689
00690 udp_recv(dhcp->pcb, dhcp_recv, netif);
00691 udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
00692 udp_connect(dhcp->pcb, IP_ADDR_BROADCAST, DHCP_SERVER_PORT);
00693
00694 DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_discover: send()ing\n"));
00695
00696 udp_send(dhcp->pcb, dhcp->p_out);
00697 DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_discover: bind()ing\n"));
00698 udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
00699 DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_discover: connect()ing\n"));
00700 udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);
00701 DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_discover: deleting()ing\n"));
00702 dhcp_delete_request(netif);
00703 DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_discover: SELECTING\n"));
00704 dhcp_set_state(dhcp, DHCP_SELECTING);
00705 } else {
00706 DEBUGF(DHCP_DEBUG | DBG_TRACE | 2, ("dhcp_discover: could not allocate DHCP request\n"));
00707 }
00708 dhcp->tries++;
00709 msecs = dhcp->tries < 4 ? (dhcp->tries + 1) * 1000 : 10 * 1000;
00710 dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
00711 DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_discover(): set request timeout %u msecs\n", msecs));
00712 return result;
00713 }
00714
00715
00721 static void dhcp_bind(struct netif *netif)
00722 {
00723 struct dhcp *dhcp = netif->dhcp;
00724 struct ip_addr sn_mask, gw_addr;
00725
00726
00727 if (dhcp->offered_t1_renew != 0xffffffffUL) {
00728
00729 DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_bind(): t1 renewal timer %lu secs\n", dhcp->offered_t1_renew));
00730 dhcp->t1_timeout = (dhcp->offered_t1_renew + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS;
00731 if (dhcp->t1_timeout == 0) dhcp->t1_timeout = 1;
00732 DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_bind(): set request timeout %u msecs\n", dhcp->offered_t1_renew*1000));
00733 }
00734
00735 if (dhcp->offered_t2_rebind != 0xffffffffUL) {
00736 DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_bind(): t2 rebind timer %lu secs\n", dhcp->offered_t2_rebind));
00737 dhcp->t2_timeout = (dhcp->offered_t2_rebind + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS;
00738 if (dhcp->t2_timeout == 0) dhcp->t2_timeout = 1;
00739 DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_bind(): set request timeout %u msecs\n", dhcp->offered_t2_rebind*1000));
00740 }
00741
00742 ip_addr_set(&sn_mask, &dhcp->offered_sn_mask);
00743
00744
00745
00746 if (sn_mask.addr == 0) {
00747
00748 u8_t first_octet = ip4_addr1(&sn_mask);
00749 if (first_octet <= 127) sn_mask.addr = htonl(0xff000000);
00750 else if (first_octet >= 192) sn_mask.addr = htonl(0xffffff00);
00751 else sn_mask.addr = htonl(0xffff0000);
00752 }
00753
00754 ip_addr_set(&gw_addr, &dhcp->offered_gw_addr);
00755
00756 if (gw_addr.addr == 0) {
00757
00758 gw_addr.addr = (dhcp->offered_ip_addr.addr & sn_mask.addr);
00759
00760 gw_addr.addr |= htonl(0x00000001);
00761 }
00762
00763 DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_bind(): IP: 0x%08lx\n", dhcp->offered_ip_addr.addr));
00764 netif_set_ipaddr(netif, &dhcp->offered_ip_addr);
00765 DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_bind(): SN: 0x%08lx\n", sn_mask.addr));
00766 netif_set_netmask(netif, &sn_mask);
00767 DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_bind(): GW: 0x%08lx\n", gw_addr.addr));
00768 netif_set_gw(netif, &gw_addr);
00769
00770 dhcp_set_state(dhcp, DHCP_BOUND);
00771 }
00772
00778 err_t dhcp_renew(struct netif *netif)
00779 {
00780 struct dhcp *dhcp = netif->dhcp;
00781 err_t result;
00782 u16_t msecs;
00783 DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_renew()\n"));
00784 dhcp_set_state(dhcp, DHCP_RENEWING);
00785
00786
00787 result = dhcp_create_request(netif);
00788 if (result == ERR_OK) {
00789
00790 dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN);
00791 dhcp_option_byte(dhcp, DHCP_REQUEST);
00792
00793 dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
00794
00795 dhcp_option_short(dhcp, 576);
00796
00797 #if 0
00798 dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4);
00799 dhcp_option_long(dhcp, ntohl(dhcp->offered_ip_addr.addr));
00800 #endif
00801
00802 #if 0
00803 dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4);
00804 dhcp_option_long(dhcp, ntohl(dhcp->server_ip_addr.addr));
00805 #endif
00806
00807 dhcp_option_trailer(dhcp);
00808
00809 pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
00810
00811 udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
00812 udp_connect(dhcp->pcb, &dhcp->server_ip_addr, DHCP_SERVER_PORT);
00813 udp_send(dhcp->pcb, dhcp->p_out);
00814 dhcp_delete_request(netif);
00815
00816 DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_renew: RENEWING\n"));
00817 } else {
00818 DEBUGF(DHCP_DEBUG | DBG_TRACE | 2, ("dhcp_renew: could not allocate DHCP request\n"));
00819 }
00820 dhcp->tries++;
00821
00822 msecs = dhcp->tries < 10 ? dhcp->tries * 2000 : 20 * 1000;
00823 dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
00824 DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_renew(): set request timeout %u msecs\n", msecs));
00825 return result;
00826 }
00827
00833 static err_t dhcp_rebind(struct netif *netif)
00834 {
00835 struct dhcp *dhcp = netif->dhcp;
00836 err_t result;
00837 u16_t msecs;
00838 DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_rebind()\n"));
00839 dhcp_set_state(dhcp, DHCP_REBINDING);
00840
00841
00842 result = dhcp_create_request(netif);
00843 if (result == ERR_OK)
00844 {
00845
00846 dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN);
00847 dhcp_option_byte(dhcp, DHCP_REQUEST);
00848
00849 dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
00850 dhcp_option_short(dhcp, 576);
00851
00852 #if 0
00853 dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4);
00854 dhcp_option_long(dhcp, ntohl(dhcp->offered_ip_addr.addr));
00855
00856 dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4);
00857 dhcp_option_long(dhcp, ntohl(dhcp->server_ip_addr.addr));
00858 #endif
00859
00860 dhcp_option_trailer(dhcp);
00861
00862 pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
00863
00864 udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
00865 udp_connect(dhcp->pcb, IP_ADDR_BROADCAST, DHCP_SERVER_PORT);
00866 udp_send(dhcp->pcb, dhcp->p_out);
00867 udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);
00868 dhcp_delete_request(netif);
00869 DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_rebind: REBINDING\n"));
00870 } else {
00871 DEBUGF(DHCP_DEBUG | DBG_TRACE | 2, ("dhcp_rebind: could not allocate DHCP request\n"));
00872 }
00873 dhcp->tries++;
00874 msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000;
00875 dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
00876 DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_rebind(): set request timeout %u msecs\n", msecs));
00877 return result;
00878 }
00879
00885 static err_t dhcp_release(struct netif *netif)
00886 {
00887 struct dhcp *dhcp = netif->dhcp;
00888 err_t result;
00889 u16_t msecs;
00890 DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_release()\n"));
00891
00892
00893 dhcp_set_state(dhcp, DHCP_OFF);
00894
00895
00896
00897 result = dhcp_create_request(netif);
00898 if (result == ERR_OK) {
00899 dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN);
00900 dhcp_option_byte(dhcp, DHCP_RELEASE);
00901
00902 dhcp_option_trailer(dhcp);
00903
00904 pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
00905
00906 udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
00907 udp_connect(dhcp->pcb, &dhcp->server_ip_addr, DHCP_SERVER_PORT);
00908 udp_send(dhcp->pcb, dhcp->p_out);
00909 dhcp_delete_request(netif);
00910 DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_release: RELEASED, DHCP_OFF\n"));
00911 } else {
00912 DEBUGF(DHCP_DEBUG | DBG_TRACE | 2, ("dhcp_release: could not allocate DHCP request\n"));
00913 }
00914 dhcp->tries++;
00915 msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000;
00916 dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
00917 DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_release(): set request timeout %u msecs\n", msecs));
00918
00919 netif_set_ipaddr(netif, IP_ADDR_ANY);
00920 netif_set_gw(netif, IP_ADDR_ANY);
00921 netif_set_netmask(netif, IP_ADDR_ANY);
00922
00923 return result;
00924 }
00930 void dhcp_stop(struct netif *netif)
00931 {
00932 struct dhcp *dhcp = netif->dhcp;
00933 DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_stop()\n"));
00934
00935 if (dhcp != NULL)
00936 {
00937 if (dhcp->pcb != NULL)
00938 {
00939 udp_remove(dhcp->pcb);
00940 dhcp->pcb = NULL;
00941 }
00942 if (dhcp->p != NULL)
00943 {
00944 pbuf_free(dhcp->p);
00945 dhcp->p = NULL;
00946 }
00947
00948 dhcp_free_reply(dhcp);
00949 mem_free((void *)dhcp);
00950 netif->dhcp = NULL;
00951 }
00952 }
00953
00954
00955
00956
00957
00958
00959
00960
00961 static void dhcp_set_state(struct dhcp *dhcp, unsigned char new_state)
00962 {
00963 if (new_state != dhcp->state)
00964 {
00965 dhcp->state = new_state;
00966 dhcp->tries = 0;
00967 }
00968 }
00969
00970
00971
00972
00973
00974
00975 static void dhcp_option(struct dhcp *dhcp, u8_t option_type, u8_t option_len)
00976 {
00977 LWIP_ASSERT("dhcp_option_short: dhcp->options_out_len + 2 + option_len <= DHCP_OPTIONS_LEN", dhcp->options_out_len + 2 + option_len <= DHCP_OPTIONS_LEN);
00978 dhcp->msg_out->options[dhcp->options_out_len++] = option_type;
00979 dhcp->msg_out->options[dhcp->options_out_len++] = option_len;
00980 }
00981
00982
00983
00984
00985 static void dhcp_option_byte(struct dhcp *dhcp, u8_t value)
00986 {
00987 LWIP_ASSERT("dhcp_option_short: dhcp->options_out_len < DHCP_OPTIONS_LEN", dhcp->options_out_len < DHCP_OPTIONS_LEN);
00988 dhcp->msg_out->options[dhcp->options_out_len++] = value;
00989 }
00990 static void dhcp_option_short(struct dhcp *dhcp, u16_t value)
00991 {
00992 LWIP_ASSERT("dhcp_option_short: dhcp->options_out_len + 2 <= DHCP_OPTIONS_LEN", dhcp->options_out_len + 2 <= DHCP_OPTIONS_LEN);
00993 dhcp->msg_out->options[dhcp->options_out_len++] = (value & 0xff00U) >> 8;
00994 dhcp->msg_out->options[dhcp->options_out_len++] = value & 0x00ffU;
00995 }
00996 static void dhcp_option_long(struct dhcp *dhcp, u32_t value)
00997 {
00998 LWIP_ASSERT("dhcp_option_long: dhcp->options_out_len + 4 <= DHCP_OPTIONS_LEN", dhcp->options_out_len + 4 <= DHCP_OPTIONS_LEN);
00999 dhcp->msg_out->options[dhcp->options_out_len++] = (value & 0xff000000UL) >> 24;
01000 dhcp->msg_out->options[dhcp->options_out_len++] = (value & 0x00ff0000UL) >> 16;
01001 dhcp->msg_out->options[dhcp->options_out_len++] = (value & 0x0000ff00UL) >> 8;
01002 dhcp->msg_out->options[dhcp->options_out_len++] = (value & 0x000000ffUL);
01003 }
01004
01015 static err_t dhcp_unfold_reply(struct dhcp *dhcp)
01016 {
01017 struct pbuf *p = dhcp->p;
01018 u8_t *ptr;
01019 u16_t i;
01020 u16_t j = 0;
01021
01022 dhcp_free_reply(dhcp);
01023 dhcp->msg_in = NULL;
01024 dhcp->options_in = NULL;
01025
01026 if (dhcp->p->tot_len > (sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN))
01027 {
01028 dhcp->options_in_len = dhcp->p->tot_len - (sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN);
01029 dhcp->options_in = mem_malloc(dhcp->options_in_len);
01030 if (dhcp->options_in == NULL)
01031 {
01032 DEBUGF(DHCP_DEBUG | DBG_TRACE | 2, ("dhcp_unfold_reply(): could not allocate dhcp->options\n"));
01033 return ERR_MEM;
01034 }
01035 }
01036 dhcp->msg_in = mem_malloc(sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN);
01037 if (dhcp->msg_in == NULL)
01038 {
01039 DEBUGF(DHCP_DEBUG | DBG_TRACE | 2, ("dhcp_unfold_reply(): could not allocate dhcp->msg_in\n"));
01040 mem_free((void *)dhcp->options_in);
01041 dhcp->options_in = NULL;
01042 return ERR_MEM;
01043 }
01044
01045 ptr = (u8_t *)dhcp->msg_in;
01046
01047 for (i = 0; i < sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN; i++)
01048 {
01049 *ptr++ = ((u8_t *)p->payload)[j++];
01050
01051 if (j == p->len)
01052 {
01053
01054 p = p->next;
01055 j = 0;
01056 }
01057 }
01058 DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_unfold_reply(): copied %u bytes into dhcp->msg_in[]\n", i));
01059 if (dhcp->options_in != NULL) {
01060 ptr = (u8_t *)dhcp->options_in;
01061
01062 for (i = 0; i < dhcp->options_in_len; i++) {
01063 *ptr++ = ((u8_t *)p->payload)[j++];
01064
01065 if (j == p->len) {
01066
01067 p = p->next;
01068 j = 0;
01069 }
01070 }
01071 DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_unfold_reply(): copied %u bytes to dhcp->options_in[]\n", i));
01072 }
01073 return ERR_OK;
01074 }
01075
01081 static void dhcp_free_reply(struct dhcp *dhcp)
01082 {
01083 if (dhcp->msg_in != NULL) {
01084 mem_free((void *)dhcp->msg_in);
01085 dhcp->msg_in = NULL;
01086 }
01087 if (dhcp->options_in) {
01088 mem_free((void *)dhcp->options_in);
01089 dhcp->options_in = NULL;
01090 dhcp->options_in_len = 0;
01091 }
01092 DEBUGF(DHCP_DEBUG, ("dhcp_free_reply(): free'd\n"));
01093 }
01094
01095
01099 static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u16_t port)
01100 {
01101 struct netif *netif = (struct netif *)arg;
01102 struct dhcp *dhcp = netif->dhcp;
01103 struct dhcp_msg *reply_msg = (struct dhcp_msg *)p->payload;
01104 u8_t *options_ptr;
01105 u8_t msg_type;
01106 u8_t i;
01107 DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_recv()\n"));
01108 DEBUGF(DHCP_DEBUG | DBG_TRACE, ("pbuf->len = %u\n", p->len));
01109 DEBUGF(DHCP_DEBUG | DBG_TRACE, ("pbuf->tot_len = %u\n", p->tot_len));
01110 dhcp->p = p;
01111 if (reply_msg->op != DHCP_BOOTREPLY) {
01112 DEBUGF(DHCP_DEBUG | DBG_TRACE | 1, ("not a DHCP reply message, but type %u\n", reply_msg->op));
01113 pbuf_free(p);
01114 }
01115
01116 for (i = 0; i < netif->hwaddr_len; i++) {
01117 if (netif->hwaddr[i] != reply_msg->chaddr[i]) {
01118 DEBUGF(DHCP_DEBUG | DBG_TRACE | 2, ("netif->hwaddr[%u]==%02x != reply_msg->chaddr[%u]==%02x\n",
01119 i, netif->hwaddr[i], i, reply_msg->chaddr[i]));
01120 pbuf_free(p);
01121 return;
01122 }
01123 }
01124
01125 if (ntohl(reply_msg->xid) != dhcp->xid) {
01126 DEBUGF(DHCP_DEBUG | DBG_TRACE | 2, ("transaction id mismatch\n"));
01127 pbuf_free(p);
01128 return;
01129 }
01130
01131 if (dhcp_unfold_reply(dhcp) != ERR_OK) {
01132 DEBUGF(DHCP_DEBUG | DBG_TRACE | 2, ("problem unfolding DHCP message - too short on memory?\n"));
01133 pbuf_free(p);
01134 return;
01135 }
01136
01137 DEBUGF(DHCP_DEBUG | DBG_TRACE, ("searching DHCP_OPTION_MESSAGE_TYPE\n"));
01138
01139 options_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_MESSAGE_TYPE);
01140 if (options_ptr == NULL) {
01141 DEBUGF(DHCP_DEBUG | DBG_TRACE | 1, ("DHCP_OPTION_MESSAGE_TYPE option not found\n"));
01142 pbuf_free(p);
01143 return;
01144 }
01145
01146
01147 msg_type = dhcp_get_option_byte(options_ptr + 2);
01148
01149 if (msg_type == DHCP_ACK) {
01150 DEBUGF(DHCP_DEBUG | DBG_TRACE | 1, ("DHCP_ACK received\n"));
01151
01152 if (dhcp->state == DHCP_REQUESTING) {
01153 dhcp_handle_ack(netif);
01154 dhcp->request_timeout = 0;
01155 #if DHCP_DOES_ARP_CHECK
01156
01157 dhcp_check(netif);
01158 #else
01159
01160 dhcp_bind(netif);
01161 #endif
01162 }
01163
01164 else if ((dhcp->state == DHCP_REBOOTING) || (dhcp->state == DHCP_REBINDING) || (dhcp->state == DHCP_RENEWING)) {
01165 dhcp->request_timeout = 0;
01166 dhcp_bind(netif);
01167 }
01168 }
01169
01170 else if ((msg_type == DHCP_NAK) &&
01171 ((dhcp->state == DHCP_REBOOTING) || (dhcp->state == DHCP_REQUESTING) ||
01172 (dhcp->state == DHCP_REBINDING) || (dhcp->state == DHCP_RENEWING ))) {
01173 DEBUGF(DHCP_DEBUG | DBG_TRACE | 1, ("DHCP_NAK received\n"));
01174 dhcp->request_timeout = 0;
01175 dhcp_handle_nak(netif);
01176 }
01177
01178 else if ((msg_type == DHCP_OFFER) && (dhcp->state == DHCP_SELECTING)) {
01179 DEBUGF(DHCP_DEBUG | DBG_TRACE | 1, ("DHCP_OFFER received in DHCP_SELECTING state\n"));
01180 dhcp->request_timeout = 0;
01181
01182 dhcp_handle_offer(netif);
01183 }
01184 pbuf_free(p);
01185 }
01186
01187
01188 static err_t dhcp_create_request(struct netif *netif)
01189 {
01190 struct dhcp *dhcp = netif->dhcp;
01191 u16_t i;
01192 LWIP_ASSERT("dhcp_create_request: dhcp->p_out == NULL", dhcp->p_out == NULL);
01193 LWIP_ASSERT("dhcp_create_request: dhcp->msg_out == NULL", dhcp->msg_out == NULL);
01194 dhcp->p_out = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct dhcp_msg), PBUF_RAM);
01195 if (dhcp->p_out == NULL) {
01196 DEBUGF(DHCP_DEBUG | DBG_TRACE | 2, ("dhcp_create_request(): could not allocate pbuf\n"));
01197 return ERR_MEM;
01198 }
01199
01200 dhcp->xid = xid++;
01201
01202 dhcp->msg_out = (struct dhcp_msg *)dhcp->p_out->payload;
01203
01204 dhcp->msg_out->op = DHCP_BOOTREQUEST;
01205
01206 dhcp->msg_out->htype = DHCP_HTYPE_ETH;
01207
01208 dhcp->msg_out->hlen = DHCP_HLEN_ETH;
01209 dhcp->msg_out->hops = 0;
01210 dhcp->msg_out->xid = htonl(dhcp->xid);
01211 dhcp->msg_out->secs = 0;
01212 dhcp->msg_out->flags = 0;
01213 dhcp->msg_out->ciaddr = netif->ip_addr.addr;
01214 dhcp->msg_out->yiaddr = 0;
01215 dhcp->msg_out->siaddr = 0;
01216 dhcp->msg_out->giaddr = 0;
01217 for (i = 0; i < DHCP_CHADDR_LEN; i++) {
01218
01219 dhcp->msg_out->chaddr[i] = (i < netif->hwaddr_len) ? netif->hwaddr[i] : 0;
01220 }
01221 for (i = 0; i < DHCP_SNAME_LEN; i++) dhcp->msg_out->sname[i] = 0;
01222 for (i = 0; i < DHCP_FILE_LEN; i++) dhcp->msg_out->file[i] = 0;
01223 dhcp->msg_out->cookie = htonl(0x63825363UL);
01224 dhcp->options_out_len = 0;
01225
01226 for (i = 0; i < DHCP_OPTIONS_LEN; i++) dhcp->msg_out->options[i] = i;
01227 return ERR_OK;
01228 }
01229
01230 static void dhcp_delete_request(struct netif *netif)
01231 {
01232 struct dhcp *dhcp = netif->dhcp;
01233 LWIP_ASSERT("dhcp_free_msg: dhcp->p_out != NULL", dhcp->p_out != NULL);
01234 LWIP_ASSERT("dhcp_free_msg: dhcp->msg_out != NULL", dhcp->msg_out != NULL);
01235 pbuf_free(dhcp->p_out);
01236 dhcp->p_out = NULL;
01237 dhcp->msg_out = NULL;
01238 }
01239
01247 static void dhcp_option_trailer(struct dhcp *dhcp)
01248 {
01249 LWIP_ASSERT("dhcp_option_trailer: dhcp->msg_out != NULL\n", dhcp->msg_out != NULL);
01250 LWIP_ASSERT("dhcp_option_trailer: dhcp->options_out_len < DHCP_OPTIONS_LEN\n", dhcp->options_out_len < DHCP_OPTIONS_LEN);
01251 dhcp->msg_out->options[dhcp->options_out_len++] = DHCP_OPTION_END;
01252
01253 while ((dhcp->options_out_len < DHCP_MIN_OPTIONS_LEN) || (dhcp->options_out_len & 3)) {
01254
01255 LWIP_ASSERT("dhcp_option_trailer: dhcp->options_out_len < DHCP_OPTIONS_LEN\n", dhcp->options_out_len < DHCP_OPTIONS_LEN);
01256
01257 dhcp->msg_out->options[dhcp->options_out_len++] = 0;
01258 }
01259 }
01260
01270 static u8_t *dhcp_get_option_ptr(struct dhcp *dhcp, u8_t option_type)
01271 {
01272 u8_t overload = DHCP_OVERLOAD_NONE;
01273
01274
01275 if ((dhcp->options_in != NULL) && (dhcp->options_in_len > 0)) {
01276
01277 u8_t *options = (u8_t *)dhcp->options_in;
01278 u16_t offset = 0;
01279
01280 while ((offset < dhcp->options_in_len) && (options[offset] != DHCP_OPTION_END)) {
01281
01282
01283 if (options[offset] == DHCP_OPTION_OVERLOAD) {
01284 DEBUGF(DHCP_DEBUG | DBG_TRACE | 2, ("overloaded message detected\n"));
01285
01286 offset += 2;
01287 overload = options[offset++];
01288 }
01289
01290 else if (options[offset] == option_type) {
01291 DEBUGF(DHCP_DEBUG | DBG_TRACE, ("option found at offset %u in options\n", offset));
01292 return &options[offset];
01293
01294 } else {
01295 DEBUGF(DHCP_DEBUG, ("skipping option %u in options\n", options[offset]));
01296
01297 offset++;
01298
01299 offset += 1 + options[offset];
01300 }
01301 }
01302
01303 if (overload != DHCP_OVERLOAD_NONE) {
01304 u16_t field_len;
01305 if (overload == DHCP_OVERLOAD_FILE) {
01306 DEBUGF(DHCP_DEBUG | DBG_TRACE | 1, ("overloaded file field\n"));
01307 options = (u8_t *)&dhcp->msg_in->file;
01308 field_len = DHCP_FILE_LEN;
01309 } else if (overload == DHCP_OVERLOAD_SNAME) {
01310 DEBUGF(DHCP_DEBUG | DBG_TRACE | 1, ("overloaded sname field\n"));
01311 options = (u8_t *)&dhcp->msg_in->sname;
01312 field_len = DHCP_SNAME_LEN;
01313
01314 } else {
01315 DEBUGF(DHCP_DEBUG | DBG_TRACE | 1, ("overloaded sname and file field\n"));
01316 options = (u8_t *)&dhcp->msg_in->sname;
01317 field_len = DHCP_FILE_LEN + DHCP_SNAME_LEN;
01318 }
01319 offset = 0;
01320
01321
01322 while ((offset < field_len) && (options[offset] != DHCP_OPTION_END)) {
01323 if (options[offset] == option_type) {
01324 DEBUGF(DHCP_DEBUG | DBG_TRACE, ("option found at offset=%u\n", offset));
01325 return &options[offset];
01326
01327 } else {
01328 DEBUGF(DHCP_DEBUG | DBG_TRACE, ("skipping option %u\n", options[offset]));
01329
01330 offset++;
01331 offset += 1 + options[offset];
01332 }
01333 }
01334 }
01335 }
01336 return 0;
01337 }
01338
01347 static u8_t dhcp_get_option_byte(u8_t *ptr)
01348 {
01349 DEBUGF(DHCP_DEBUG, ("option byte value=%u\n", *ptr));
01350 return *ptr;
01351 }
01352
01361 static u16_t dhcp_get_option_short(u8_t *ptr)
01362 {
01363 u16_t value;
01364 value = *ptr++ << 8;
01365 value |= *ptr;
01366 DEBUGF(DHCP_DEBUG, ("option short value=%u\n", value));
01367 return value;
01368 }
01369
01378 static u32_t dhcp_get_option_long(u8_t *ptr)
01379 {
01380 u32_t value;
01381 value = (u32_t)(*ptr++) << 24;
01382 value |= (u32_t)(*ptr++) << 16;
01383 value |= (u32_t)(*ptr++) << 8;
01384 value |= (u32_t)(*ptr++);
01385 DEBUGF(DHCP_DEBUG, ("option long value=%lu\n", value));
01386 return value;
01387 }