Ejemplo n.º 1
0
/****************************************************************************
 * Name: dhcpc_request
 ****************************************************************************/
static int dhcpc_request(void *handle, struct dhcpc_state *presult)
{
	if (!handle) {
		ndbg("ERROR : handle must not be null\n");
		return -100;
	}

	if (!presult) {
		ndbg("ERROR : presult must not be null\n");
		return -100;
	}

	struct dhcpc_state_s *pdhcpc = (struct dhcpc_state_s *)handle;
	g_pResult = presult;
	struct in_addr oldaddr;
	struct in_addr newaddr;
	uint8_t msgtype;
	int retries = 0, result = 0;
	char *intf;
#define CNT_MAX_DISCOVER 5
#define CNT_MAX_REQUEST 5
	/* Save the currently assigned IP address (should be INADDR_ANY) */
	oldaddr.s_addr = 0;

	intf = pdhcpc->nic;
	int ret = netlib_get_ipv4addr(intf, &oldaddr);
	if (ret == -1) {
		printf("Set IPv4 fail\n");
	}

	/* Loop until we receive the lease (or an error occurs) */
	/* Set the IP address to INADDR_ANY. */
	newaddr.s_addr = INADDR_ANY;
	if (netlib_set_ipv4addr(intf, &newaddr) == ERROR) {
		ndbg("netlib_set_ipv4addr failed\n");
	}

	/* Loop sending DISCOVER until we receive an OFFER from a DHCP
	 * server.  We will lock on to the first OFFER and decline any
	 * subsequent offers (which will happen if there are more than one
	 * DHCP servers on the network.
	 */
	g_dhcpc_state = STATE_INITIAL;
	do {
		/* Get the DHCPOFFER response */
		if (++retries > CNT_MAX_DISCOVER) {	/* reach max try */
			return -2;
		}

		ndbg("Send Discover Packet\n");
		result = dhcpc_sendmsg(pdhcpc, g_pResult, DHCPDISCOVER);
		usleep(100000);
		if (result < 0) {
			if (get_errno() == EAGAIN) {
				continue;
			}
			ndbg("sendDiscover Error\n");
			return -1;
		}

		ndbg("Waiting Offer...(%d)\n", pdhcpc->sockfd);
		result = recv(pdhcpc->sockfd, &pdhcpc->packet, sizeof(struct dhcp_msg), 0);
		ndbg("Received...(%d)\n", result);

		if (result <= 0) {
			ndbg("receive fail\n");
			continue;
		}
		msgtype = dhcpc_parsemsg(pdhcpc, result, presult);
		if (msgtype == DHCPOFFER) {
			/* Save the servid from the presult so that it is not clobbered
			 * by a new OFFER.
			 */
			ndbg("Received OFFER from %08x\n", ntohl(presult->serverid.s_addr));
			pdhcpc->ipaddr.s_addr = presult->ipaddr.s_addr;
			pdhcpc->serverid.s_addr = presult->serverid.s_addr;

			/* Temporarily use the address offered by the server and break
			 * out of the loop.
			 */

			ret = netlib_set_ipv4addr(intf, &presult->ipaddr);
			if (ret == -1) {
				ndbg("Set IPv4 fail\n");
			}
			g_dhcpc_state = STATE_HAVE_OFFER;
			break;
		} else {
			ndbg("Received AnotherData %d %x\n", result, msgtype);
		}
	} while (g_dhcpc_state == STATE_INITIAL);

	/* Loop sending the REQUEST up to three times (if there is no response) */
	retries = 0;

	/* Send the REQUEST message to obtain the lease that was offered to us. */
	ndbg("Send REQUEST\n");

	do {
		if (retries++ > CNT_MAX_REQUEST)
			break;

		ndbg("Send Request Packet\n");

		result = dhcpc_sendmsg(pdhcpc, g_pResult, DHCPREQUEST);
		if (result < 0) {
			ndbg("thread_sendRequest Error\n");
			return -3;
		}
		usleep(100000);
		/* Get the ACK/NAK response to the REQUEST (or timeout) */
		ndbg("Waiting Ack...\n");
		result = recv(pdhcpc->sockfd, &pdhcpc->packet, sizeof(struct dhcp_msg), 0);
		ndbg("Received...(%d)\n", result);

		if (result <= 0) {
			ndbg("recv request error(%d)(%d)\n", result, errno);
			continue;
		}

		/* Parse the response */
		ndbg("Data Received\n");

		msgtype = dhcpc_parsemsg(pdhcpc, result, presult);

		/* The ACK response means that the server has accepted our request
		 * and we have the lease.
		 */

		if (msgtype == DHCPACK) {
			ndbg("Received ACK\n");
			g_dhcpc_state = STATE_HAVE_LEASE;

		}

		/* NAK means the server has refused our request.  Break out of
		 * this loop with state == STATE_HAVE_OFFER and send DISCOVER again
		 */

		else if (msgtype == DHCPNAK) {
			ndbg("Received NAK\n");
			break;
		}

		/* If we get any OFFERs from other servers, then decline them now
		 * and continue waiting for the ACK from the server that we
		 * requested from.
		 */

		else if (msgtype == DHCPOFFER) {
			/* If we get OFFERs from same dhcp server, do not send DECLINE */
			if (pdhcpc->serverid.s_addr == presult->serverid.s_addr) {
				ndbg("Received duplicated OFFER from %08x\n", ntohl(presult->serverid.s_addr));
			} else {
				ndbg("Received another OFFER from %08x, send DECLINE\n", ntohl(presult->serverid.s_addr));
				result = dhcpc_sendmsg(pdhcpc, presult, DHCPDECLINE);
				if (result <= 0) {
					ndbg("recv request error(%d)(%d)\n", result, errno);
				}
			}
		}

		/* Otherwise, it is something that we do not recognize */

		else {
			ndbg("Ignoring msgtype=%d %d\n", msgtype, result);
		}
		usleep(100000L);

		/* An error has occurred.  If this was a timeout error (meaning
		 * that nothing was received on this socket for a long period of time).
		 * Then break out and send the DISCOVER command again (at most
		 * 3 times).
		 */
	} while (g_dhcpc_state == STATE_HAVE_OFFER);

	ndbg("Got IP address %d.%d.%d.%d\n", (presult->ipaddr.s_addr) & 0xff, (presult->ipaddr.s_addr >> 8) & 0xff, (presult->ipaddr.s_addr >> 16) & 0xff, (presult->ipaddr.s_addr >> 24) & 0xff);
	ndbg("Got netmask %d.%d.%d.%d\n", (presult->netmask.s_addr) & 0xff, (presult->netmask.s_addr >> 8) & 0xff, (presult->netmask.s_addr >> 16) & 0xff, (presult->netmask.s_addr >> 24) & 0xff);
	ndbg("Got DNS server %d.%d.%d.%d\n", (presult->dnsaddr.s_addr) & 0xff, (presult->dnsaddr.s_addr >> 8) & 0xff, (presult->dnsaddr.s_addr >> 16) & 0xff, (presult->dnsaddr.s_addr >> 24) & 0xff);
	ndbg("Got default router %d.%d.%d.%d\n", (presult->default_router.s_addr) & 0xff, (presult->default_router.s_addr >> 8) & 0xff, (presult->default_router.s_addr >> 16) & 0xff, (presult->default_router.s_addr >> 24) & 0xff);
	ndbg("Lease expires in %d seconds\n", presult->lease_time);

#if defined CONFIG_NET_LWIP    // this is temporal fix. it should be modified later
    ip_addr_t dns_addr;
    IP_SET_TYPE_VAL(dns_addr, IPADDR_TYPE_V4);
#ifdef CONFIG_NET_IPv6
    dns_addr.u_addr.ip4.addr = presult->dnsaddr.s_addr;
#else
    dns_addr.addr = presult->dnsaddr.s_addr;
#endif
    dns_setserver(0, &dns_addr);
#endif /*  CONFIG_NET_LWIP */

#if defined(CONFIG_NETDB_DNSCLIENT) && defined(CONFIG_NETDB_DNSSERVER_BY_DHCP)
	struct sockaddr_in dns;
	if (presult->dnsaddr.s_addr != 0) {
		ndbg("Set DNS IP address via dns_add_nameserver\n");
		dns.sin_addr.s_addr = presult->dnsaddr.s_addr;
		dns.sin_family = AF_INET;
		dns.sin_port  = htons(DNS_DEFAULT_PORT);
		dns_add_nameserver((FAR struct sockaddr *)&dns, sizeof(struct sockaddr_in));
	}
#endif

	return OK;
}
Ejemplo n.º 2
0
int dhcpc_request(void *handle, struct dhcpc_state *presult)
{
  struct dhcpc_state_s *pdhcpc = (struct dhcpc_state_s *)handle;
  struct in_addr oldaddr;
  struct in_addr newaddr;
  ssize_t result;
  uint8_t msgtype;
  int     retries;
  int     state;

  /* Save the currently assigned IP address (should be INADDR_ANY) */

  oldaddr.s_addr = 0;
  uip_gethostaddr("eth0", &oldaddr);

  /* Loop until we receive the lease (or an error occurs) */

  do
    {
      /* Set the IP address to INADDR_ANY. */

      newaddr.s_addr = INADDR_ANY;
      (void)uip_sethostaddr("eth0", &newaddr);

      /* Loop sending DISCOVER until we receive an OFFER from a DHCP
       * server.  We will lock on to the first OFFER and decline any
       * subsequent offers (which will happen if there are more than one
       * DHCP servers on the network.
       */

      state = STATE_INITIAL;
      do
        {
          /* Send the DISCOVER command */

          dbg("Broadcast DISCOVER\n");
          if (dhcpc_sendmsg(pdhcpc, presult, DHCPDISCOVER) < 0)
            {
              return ERROR;
            }

          /* Get the DHCPOFFER response */

          result = recv(pdhcpc->sockfd, &pdhcpc->packet, sizeof(struct dhcp_msg), 0);
          if (result >= 0)
            {
              msgtype = dhcpc_parsemsg(pdhcpc, result, presult);
              if (msgtype == DHCPOFFER)
                {
                  /* Save the servid from the presult so that it is not clobbered
                   * by a new OFFER.
                   */

                  dbg("Received OFFER from %08x\n", ntohl(presult->serverid.s_addr));
                  pdhcpc->ipaddr.s_addr   = presult->ipaddr.s_addr;
                  pdhcpc->serverid.s_addr = presult->serverid.s_addr;

                  /* Temporarily use the address offered by the server and break
                   * out of the loop.
                   */

                  (void)uip_sethostaddr("eth0", &presult->ipaddr);
                  state = STATE_HAVE_OFFER;
                }
            }

          /* An error has occurred.  If this was a timeout error (meaning that
           * nothing was received on this socket for a long period of time).
           * Then loop and send the DISCOVER command again.
           */

          else if (errno != EAGAIN)
            {
              /* An error other than a timeout was received -- error out */

              return ERROR;
            }
        }
      while (state == STATE_INITIAL);


      /* Loop sending the REQUEST up to three times (if there is no response) */

      retries = 0;
      do
        {
          /* Send the REQUEST message to obtain the lease that was offered to us. */

          dbg("Send REQUEST\n");
          if (dhcpc_sendmsg(pdhcpc, presult, DHCPREQUEST) < 0)
            {
              return ERROR;
            }
          retries++;

          /* Get the ACK/NAK response to the REQUEST (or timeout) */

          result = recv(pdhcpc->sockfd, &pdhcpc->packet, sizeof(struct dhcp_msg), 0);
          if (result >= 0)
            {
              /* Parse the response */

              msgtype = dhcpc_parsemsg(pdhcpc, result, presult);

              /* The ACK response means that the server has accepted our request
               * and we have the lease.
               */

              if (msgtype == DHCPACK)
                {
                  dbg("Received ACK\n");
                  state = STATE_HAVE_LEASE;
                }

              /* NAK means the server has refused our request.  Break out of
               * this loop with state == STATE_HAVE_OFFER and send DISCOVER again
               */

              else if (msgtype == DHCPNAK)
                {
                  dbg("Received NAK\n");
                  break;
                }

              /* If we get any OFFERs from other servers, then decline them now
               * and continue waiting for the ACK from the server that we
               * requested from.
               */

              else if (msgtype == DHCPOFFER)
                {
                  dbg("Received another OFFER, send DECLINE\n");
                  (void)dhcpc_sendmsg(pdhcpc, presult, DHCPDECLINE);
                }

              /* Otherwise, it is something that we do not recognize */

              else
                {
                  dbg("Ignoring msgtype=%d\n", msgtype);
                }
            }

          /* An error has occurred.  If this was a timeout error (meaning
           * that nothing was received on this socket for a long period of time).
           * Then break out and send the DISCOVER command again (at most
           * 3 times).
           */

          else if (errno != EAGAIN)
            {
              /* An error other than a timeout was received */

              (void)uip_sethostaddr("eth0", &oldaddr);
              return ERROR;
            }
        }
      while (state == STATE_HAVE_OFFER && retries < 3);
    }
  while (state != STATE_HAVE_LEASE);

  dbg("Got IP address %d.%d.%d.%d\n",
      (presult->ipaddr.s_addr >> 24 ) & 0xff,
      (presult->ipaddr.s_addr >> 16 ) & 0xff,
      (presult->ipaddr.s_addr >> 8  ) & 0xff,
      (presult->ipaddr.s_addr       ) & 0xff);
  dbg("Got netmask %d.%d.%d.%d\n",
      (presult->netmask.s_addr >> 24 ) & 0xff,
      (presult->netmask.s_addr >> 16 ) & 0xff,
      (presult->netmask.s_addr >> 8  ) & 0xff,
      (presult->netmask.s_addr       ) & 0xff);
  dbg("Got DNS server %d.%d.%d.%d\n",
      (presult->dnsaddr.s_addr >> 24 ) & 0xff,
      (presult->dnsaddr.s_addr >> 16 ) & 0xff,
      (presult->dnsaddr.s_addr >> 8  ) & 0xff,
      (presult->dnsaddr.s_addr       ) & 0xff);
  dbg("Got default router %d.%d.%d.%d\n",
      (presult->default_router.s_addr >> 24 ) & 0xff,
      (presult->default_router.s_addr >> 16 ) & 0xff,
      (presult->default_router.s_addr >> 8  ) & 0xff,
      (presult->default_router.s_addr       ) & 0xff);
  dbg("Lease expires in %d seconds\n", presult->lease_time);
  return OK;
}