void dhcp_process_packet(FullPacket *p) { DhcpHead *dhcp = &p->dhcp; uint8_t *current = dhcp->options + 4; for ( ; current <= dhcp->options + 64 && *current != OPTION_END; current += current[1]+2 /* 2 == size of code + len */) { if (*current != OPTION_DHCP_MESSAGE_TYPE) continue; switch(current[2]) { case DHCPOFFER: printf("DHCPOFFER ip: "); print_ip(dhcp->yiaddr); printf("\r\n"); dhcp_request(p); return; case DHCPACK: printf("ACK Received\r\n"); dhcp_handle_ack(p); return; default: break; } } }
/** * Match incoming DHCP messages against a DHCP client, and trigger its state machine */ static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u16_t port) { struct dhcp_state *state = (struct dhcp_state *)arg; struct dhcp_msg *reply_msg = (struct dhcp_msg *)p->payload; DEBUGF(DHCP_DEBUG, ("dhcp_recv()\n")); DEBUGF(DHCP_DEBUG, ("pbuf->len = %u\n", p->len)); DEBUGF(DHCP_DEBUG, ("pbuf->tot_len = %u\n", p->tot_len)); state->p = p; if (reply_msg->op == DHCP_BOOTREPLY) { DEBUGF(DHCP_DEBUG, ("state->netif->hwaddr = %02x:%02x:%02x:%02x:%02x:%02x\n", state->netif->hwaddr[0], state->netif->hwaddr[1], state->netif->hwaddr[2], state->netif->hwaddr[3], state->netif->hwaddr[4], state->netif->hwaddr[5])); // TODO: Add multi network interface support, look up the targetted // interface here. if ((state->netif->hwaddr[0] == reply_msg->chaddr[0]) && (state->netif->hwaddr[1] == reply_msg->chaddr[1]) && (state->netif->hwaddr[2] == reply_msg->chaddr[2]) && (state->netif->hwaddr[3] == reply_msg->chaddr[3]) && (state->netif->hwaddr[4] == reply_msg->chaddr[4]) && (state->netif->hwaddr[5] == reply_msg->chaddr[5])) { // check if the transaction ID matches if (get_reply_xid(reply_msg) == state->xid) { // option fields could be unfold? if (dhcp_unfold_reply(state) == ERR_OK) { u8_t *options_ptr = NULL; DEBUGF(DHCP_DEBUG, ("searching DHCP_OPTION_MESSAGE_TYPE\n")); options_ptr = dhcp_get_option_ptr(state, DHCP_OPTION_MESSAGE_TYPE); if (options_ptr != NULL) { u8_t msg_type = dhcp_get_option_byte(options_ptr + 2); if (msg_type == DHCP_ACK) { DEBUGF(DHCP_DEBUG, ("DHCP_ACK received\n")); if (state->state == DHCP_REQUESTING) { dhcp_handle_ack(state); state->request_timeout = 0; #if DHCP_DOES_ARP_CHECK dhcp_check(state); #else dhcp_bind(state); #endif } else if ((state->state == DHCP_REBOOTING) || (state->state == DHCP_REBINDING) ||(state->state == DHCP_RENEWING)) { state->request_timeout = 0; dhcp_bind(state); } } // received a DHCP_NAK in appropriate state? else if ((msg_type == DHCP_NAK) && ((state->state == DHCP_REBOOTING) || (state->state == DHCP_REQUESTING) || (state->state == DHCP_REBINDING) || (state->state == DHCP_RENEWING ))) { DEBUGF(DHCP_DEBUG, ("DHCP_NAK received\n")); state->request_timeout = 0; dhcp_handle_nak(state); } // received a DHCP_OFFER in DHCP_SELECTING state? else if ((msg_type == DHCP_OFFER) && (state->state == DHCP_SELECTING)) { DEBUGF(DHCP_DEBUG, ("DHCP_OFFER received in DHCP_SELECTING state\n")); state->request_timeout = 0; dhcp_handle_offer(state); } } else { DEBUGF(DHCP_DEBUG, ("DHCP_OPTION_MESSAGE_TYPE option not found\n")); } dhcp_free_reply(state); } } else { DEBUGF(DHCP_DEBUG, ("reply_msg->xid=%x does not match with state->xid=%x\n", get_reply_xid(reply_msg), state->xid)); } } else { DEBUGF(DHCP_DEBUG, ("hardware address did not match\n")); DEBUGF(DHCP_DEBUG, ("reply_msg->chaddr = %02x:%02x:%02x:%02x:%02x:%02x\n", reply_msg->chaddr[0], reply_msg->chaddr[1], reply_msg->chaddr[2], reply_msg->chaddr[3], reply_msg->chaddr[4], reply_msg->chaddr[5])); } } else { DEBUGF(DHCP_DEBUG, ("not a DHCP reply message, but type %u\n", reply_msg->op)); } pbuf_free(p); }