⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dhcpd.c

📁 這是一個實時嵌入式作業系統 實作了MCS51 ARM等MCU
💻 C
📖 第 1 页 / 共 3 页
字号:
  /* Send the offer response */  return dhcpd_sendpacket(FALSE);}/**************************************************************************** * Name: dhcpd_sendnak ****************************************************************************/static int dhcpd_sendnak(void){  /* Initialize and send the NAK response */  dhcpd_initpacket(DHCPNAK);  memcpy(g_state.ds_outpacket.ciaddr, g_state.ds_inpacket.ciaddr, 4);  return dhcpd_sendpacket(TRUE);}/**************************************************************************** * Name: dhcpd_sendack ****************************************************************************/int dhcpd_sendack(in_addr_t ipaddr){  uint32 leasetime = CONFIG_NETUTILS_DHCPD_LEASETIME;  /* Initialize the ACK response */  dhcpd_initpacket(DHCPACK);  memcpy(g_state.ds_outpacket.ciaddr, g_state.ds_inpacket.ciaddr, 4);  /* Add the IP address assigned to the client */  memcpy(g_state.ds_outpacket.yiaddr, &ipaddr, 4);  /* Did the client request a specific lease time? */  (void)dhcpd_verifyreqleasetime(&leasetime);  /* Add the lease time to the response */  dhcpd_addoption32(DHCP_OPTION_LEASE_TIME, htonl(leasetime));  if (dhcpd_sendpacket(FALSE) < 0)    {      return ERROR;    }  dhcpd_setlease(g_state.ds_inpacket.chaddr, ipaddr, leasetime);  return OK;}/**************************************************************************** * Name: dhcpd_discover ****************************************************************************/static inline int dhcpd_discover(void){  struct lease_s *lease;  in_addr_t ipaddr;  uint32 leasetime = CONFIG_NETUTILS_DHCPD_LEASETIME;  /* Check if the client is aleady in the lease table */  lease = dhcpd_findbymac(g_state.ds_inpacket.chaddr);  if (lease)    {      /* Yes... get the remaining time on the lease */#ifdef HAVE_LEASE_TIME      if (!dhcpd_leaseexpired(lease))        {          leasetime = lease->expiry - dhcpd_time();          if (leasetime < CONFIG_NETUTILS_DHCPD_MINLEASETIME)            {              leasetime = CONFIG_NETUTILS_DHCPD_MINLEASETIME;            }        }#endif      /* Get the IP address associated with the lease */      ipaddr = dhcp_leaseipaddr(lease);    }  /* Check if the client has requested a specific IP address */  else if (dhcpd_verifyreqip())    {      /* Use the requested IP address */      ipaddr = g_state.ds_optreqip;    }  else    {      /* No... allocate a new IP address */      ipaddr = dhcpd_allocipaddr();    }  /* Did we get any IP address? */  if (!ipaddr)    {      /* Nope... return failure */      dbg("Failed to get IP address\n");      return ERROR;    }  /* Reserve the leased IP for a shorter time for the offer */  if (!dhcpd_setlease(g_state.ds_inpacket.chaddr, ipaddr, CONFIG_NETUTILS_DHCPD_OFFERTIME))    {      dbg("Failed to set lease\n");      return ERROR;    }  /* Check if the client has requested a specific lease time */  (void)dhcpd_verifyreqleasetime(&leasetime);  /* Send the offer response */  return dhcpd_sendoffer(ipaddr, leasetime);}/**************************************************************************** * Name: dhcpd_request ****************************************************************************/static inline int dhcpd_request(void){  struct lease_s *lease;  in_addr_t ipaddr;  uint8 response = 0;  /* Check if this client already holds a lease.  This can happen when the client (1)   * the IP is reserved for the client from a previous offer, or (2) the client is   * re-initializing or rebooting while the lease is still valid.   */  lease = dhcpd_findbymac(g_state.ds_inpacket.chaddr);  if (lease)    {      /* Yes.. the client already holds a lease.  Verify that the request is consistent       * with the existing lease.       */      ipaddr = dhcp_leaseipaddr(lease);      if (g_state.ds_optserverip)        {          /* ACK if the serverip is correct and the requested IP address is the one           * already offered to the client.            */          if (g_state.ds_optserverip == ntohl(g_state.ds_serverip) &&             (g_state.ds_optreqip != 0 || g_state.ds_optreqip == ipaddr))            {              response = DHCPACK;            }          else            {              response = DHCPNAK;            }        }      /* We have the lease and no server IP was requested. Was as specific IP address       * requested?       */      else if (g_state.ds_optreqip)        {          /* Yes..ACK if the requested IP address is the one already leased */          if (ipaddr == g_state.ds_optreqip)            {              response = DHCPACK;            }          else            {              response = DHCPNAK;            }        }      /* The client has specified neither a server IP nor requested IP address */      else        {          /* ACK if the IP used by the client is the one already assigned to it */          if (memcmp(&ipaddr, g_state.ds_inpacket.ciaddr, 4) == 0)            {              response = DHCPACK;            }          else            {              response = DHCPNAK;            }        }    }  /* The client does not hold a lease (referenced by its MAC address) and is   * requesting a specific IP address that was, apparently, never offered to   * to the client.  Perform some sanity checks before sending the NAK.   */  else if (g_state.ds_optreqip && !g_state.ds_optserverip)    {      /* Is this IP address already assigned? */      lease = dhcpd_findbyipaddr(g_state.ds_optreqip);      if (lease)        {          /* Yes.. Send NAK unless the lease has expired */          if (!dhcpd_leaseexpired(lease))            {              response = DHCPNAK;            }        }      /* No.. is the requested IP address in range? NAK if not */      else if (g_state.ds_optreqip < CONFIG_NETUTILS_DHCPD_STARTIP ||               g_state.ds_optreqip > CONFIG_NETUTILS_DHCP_OPTION_ENDIP)        {          response = DHCPNAK;        }    }  /* Finally, either (1) send the ACK, (2) send a NAK, or (3) remain silent   * based on the checks above.   */  if (response == DHCPACK)    {      dhcpd_sendack(ipaddr);    }  else if (response == DHCPNAK)    {      dhcpd_sendnak();    }  return OK;}/**************************************************************************** * Name: dhcpd_decline ****************************************************************************/static inline int dhcpd_decline(void){  struct lease_s *lease;  /* Find the lease associated with this hardware address */  lease = dhcpd_findbymac(g_state.ds_inpacket.chaddr);  if (lease)    {       /* Disassociate the IP from the MAC, but prevent re-used of this        * address for a period of time.        */       memset(lease->mac, 0, DHCP_HLEN_ETHERNET);#ifdef HAVE_LEASE_TIME       lease->expiry = dhcpd_time() + CONFIG_NETUTILS_DHCPD_DECLINETIME;#endif     }  return OK;}static inline int dhcpd_release(void){  struct lease_s *lease;  /* Find the lease associated with this hardware address */  lease = dhcpd_findbymac(g_state.ds_inpacket.chaddr);  if (lease)    {      /* Release the IP address now */      memset(lease, 0, sizeof(struct lease_s));    }  return OK;}/**************************************************************************** * Name: dhcpd_openlistener ****************************************************************************/static inline int dhcpd_openlistener(void){  struct sockaddr_in addr;  struct ifreq req;  int sockfd;  int ret;  /* Create a socket to listen for requests from DHCP clients */  sockfd = dhcpd_socket();  if (sockfd < 0)    {      dbg("socket failed: %d\n", errno);      return ERROR;    }  /* Get the IP address of the selected device */  strncpy(req.ifr_name, CONFIG_NETUTILS_DHCPD_INTERFACE, IFNAMSIZ);  ret = ioctl(sockfd, SIOCGIFADDR, (unsigned long)&req);  if (ret < 0)    {      dbg("setsockopt SIOCGIFADDR failed: %d\n", errno);      close(sockfd);      return ERROR;    }  g_state.ds_serverip = ((struct sockaddr_in*)&req.ifr_addr)->sin_addr.s_addr;  vdbg("serverip: %08x\n", ntohl(g_state.ds_serverip));  /* Bind the socket to a local port. We have to bind to INADDRY_ANY to   * receive broadcast messages.   */  addr.sin_family      = AF_INET;  addr.sin_port        = htons(DHCP_SERVER_PORT);  addr.sin_addr.s_addr = INADDR_ANY;  ret = bind(sockfd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in));  if (ret < 0)   {      dbg("bind failed: %d\n", errno);     close(sockfd);     return ERROR;   }  return sockfd;}/**************************************************************************** * Public Functions ****************************************************************************//**************************************************************************** * Name: dhcpd_run ****************************************************************************/int dhcpd_run(void){  int sockfd;  int nbytes;  vdbg("Started\n");  /* Initialize everything to zero */  memset(&g_state, 0, sizeof(struct dhcpd_state_s));  /* Now loop indefinitely, reading packets from the DHCP server socket */  sockfd = -1;  for (;;)    {      /* Create a socket to listen for requests from DHCP clients */      if (sockfd < 0)        {          sockfd = dhcpd_openlistener();          if (sockfd < 0)            {                dbg("Failed to create socket\n");                break;            }        }      /* Read the next g_state.ds_outpacket */      nbytes = recv(sockfd, &g_state.ds_inpacket, sizeof(struct dhcpmsg_s), 0);      if (nbytes < 0)        {          /* On errors (other EINTR), close the socket and try again */          dbg("recv failed: %d\n", errno);          if (errno != EINTR)            {              close(sockfd);              sockfd = -1;            }          continue;        }      /* Parse the incoming message options */      if (!dhcpd_parseoptions())        {          /* Failed to parse the message options */          dbg("No msg type\n");          continue;        }#ifdef CONFIG_NETUTILS_DHCPD_HOST      /* Get the poor little uC a change to get its recvfrom in place */      usleep(500*1000);#endif      /* Now process the incoming DHCP message by its message type */      switch (g_state.ds_optmsgtype)        {          case DHCPDISCOVER:            vdbg("DHCPDISCOVER\n");            dhcpd_discover();            break;          case DHCPREQUEST:            vdbg("DHCPREQUEST\n");            dhcpd_request();            break;          case DHCPDECLINE:            vdbg("DHCPDECLINE\n");            dhcpd_decline();            break;          case DHCPRELEASE:            vdbg("DHCPRELEASE\n");            dhcpd_release();            break;          case DHCPINFORM: /* Not supported */          default:            dbg("Unsupported message type: %d\n", g_state.ds_optmsgtype);            break;        }    }  return OK;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -