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

📄 dhcpd.c

📁 這是一個實時嵌入式作業系統 實作了MCS51 ARM等MCU
💻 C
📖 第 1 页 / 共 3 页
字号:
  g_state.ds_optleasetime = 0;    /* Requested lease time (host order) */  g_state.ds_optend       = NULL;  do    {      /* The form of an option is:       *   code   - 1 byte       *   length - 1 byte       *   data   - variable number of bytes       */      switch (ptr[DHCPD_OPTION_CODE])        {          /* Skip over any padding bytes */          case DHCP_OPTION_PAD:            optlen = 1;            break;          /* the Overload option is used to indicate that the DHCP 'sname' or 'file'           * fields are being overloaded by using them to carry DHCP options. A DHCP           * server inserts this option if the returned parameters will exceed the           * usual space allotted for options.           *           * If this option is present, the client interprets the specified additional           * fields after it concludes interpretation of the standard option fields.           *           * Legal values for this option are:           *           *   1     the 'file' field is used to hold options           *   2     the 'sname' field is used to hold options           *   3     both fields are used to hold options           */#ifndef CONFIG_NET_DHCP_LIGHT          case DHCP_OPTION_OVERLOAD:            optlen = ptr[DHCPD_OPTION_LENGTH] + 2;            if (optlen >= 1 && optlen < remaining)              {                overloaded = ptr[DHCPD_OPTION_DATA];              }            break;#endif          case DHCP_OPTION_END:#ifndef CONFIG_NET_DHCP_LIGHT            if (currfield == DHCPD_OPTION_FIELD &&                (overloaded & DHCPD_FILE_FIELD) != 0)              {                ptr       = g_state.ds_inpacket.file;                remaining = sizeof(g_state.ds_inpacket.file);                currfield = DHCPD_FILE_FIELD;              }            else if (currfield == DHCPD_FILE_FIELD &&                     (overloaded & DHCPD_SNAME_FIELD) != 0)              {                ptr       = g_state.ds_inpacket.sname;                remaining = sizeof(g_state.ds_inpacket.sname);                currfield = DHCPD_SNAME_FIELD;              }            else              {                return TRUE;              }            break;#else            return TRUE;#endif          case DHCP_OPTION_REQ_IPADDR: /* Requested IP Address */            optlen = ptr[DHCPD_OPTION_LENGTH] + 2;            if (optlen >= 4 && optlen < remaining)              {                memcpy(&tmp, &ptr[DHCPD_OPTION_DATA], 4);                g_state.ds_optreqip = (in_addr_t)ntohl(tmp);              }            break;          case DHCP_OPTION_LEASE_TIME: /* IP address lease time */             optlen = ptr[DHCPD_OPTION_LENGTH] + 2;            if (optlen >= 4 && optlen < remaining)              {                memcpy(&tmp, &ptr[DHCPD_OPTION_DATA], 4);                g_state.ds_optleasetime = (time_t)ntohl(tmp);              }            break;         case DHCP_OPTION_MSG_TYPE: /* DHCP message type */            optlen = ptr[DHCPD_OPTION_LENGTH] + 2;            if (optlen >= 1 && optlen < remaining)              {                g_state.ds_optmsgtype = ptr[DHCPD_OPTION_DATA];              }            break;          case DHCP_OPTION_SERVER_ID: /* Server identifier */            optlen = ptr[DHCPD_OPTION_LENGTH] + 2;            if (optlen >= 4 && optlen < remaining)              {                memcpy(&tmp, &ptr[DHCPD_OPTION_DATA], 4);                g_state.ds_optserverip = (in_addr_t)ntohl(tmp);              }            break;          default:            /* Skip over unsupported options */            optlen = ptr[DHCPD_OPTION_LENGTH] + 2;            break;        }      /* Advance to the next option */      ptr       += optlen;      remaining -= optlen;    }  while (remaining > 0);  return FALSE;}/**************************************************************************** * Name: dhcpd_verifyreqip ****************************************************************************/static inline boolean dhcpd_verifyreqip(void){  struct lease_s *lease;  /* Verify that the requested IP address is within the supported lease range */  if (g_state.ds_optreqip > 0 &&      g_state.ds_optreqip >= CONFIG_NETUTILS_DHCPD_STARTIP &&      g_state.ds_optreqip <= CONFIG_NETUTILS_DHCP_OPTION_ENDIP)    {      /* And verify that the lease has not already been taken or offered       * (unless the lease/offer is expired, then the address is free game).       */      lease = dhcpd_findbyipaddr(g_state.ds_optreqip);      if (!lease || dhcpd_leaseexpired(lease))        {          return TRUE;        }    }  return FALSE;}/**************************************************************************** * Name: dhcpd_verifyreqleasetime ****************************************************************************/static inline boolean dhcpd_verifyreqleasetime(uint32 *leasetime){  uint32 tmp = g_state.ds_optleasetime;  /* Did the client request a specific lease time? */  if (tmp != 0)    {      /* Yes..  Verify that the requested lease time is within a valid range */      if (tmp > CONFIG_NETUTILS_DHCPD_MAXLEASETIME)        {          tmp = CONFIG_NETUTILS_DHCPD_MAXLEASETIME;        }      else if (tmp < CONFIG_NETUTILS_DHCPD_MINLEASETIME)        {          tmp = CONFIG_NETUTILS_DHCPD_MINLEASETIME;        }      /* Return the clipped lease time */      *leasetime = tmp;      return TRUE;    }  return FALSE;}/**************************************************************************** * Name: dhcpd_addoption ****************************************************************************/static int dhcpd_addoption(uint8 *option){  int offset;  int len = 4;  if (g_state.ds_optend)    {      offset = g_state.ds_outpacket.options - g_state.ds_optend;      len    = option[DHCPD_OPTION_LENGTH] + 2;      /* Check if the option will fit into the options array */      if (offset + len + 1 < DHCPD_OPTIONS_SIZE)        {          /* Copy the option into the option array */          memcpy(g_state.ds_optend, option, len);          g_state.ds_optend += len;         *g_state.ds_optend  = DHCP_OPTION_END;        }    }  return len;}/**************************************************************************** * Name: dhcpd_addoption8 ****************************************************************************/static int dhcpd_addoption8(uint8 code, uint8 value){  uint8 option[3];  /* Construct the option sequence */  option[DHCPD_OPTION_CODE]   = code;  option[DHCPD_OPTION_LENGTH] = 1;  option[DHCPD_OPTION_DATA]   = value;  /* Add the option sequence to the response */  return dhcpd_addoption(option);}/**************************************************************************** * Name: dhcpd_addoption32 ****************************************************************************/static int dhcpd_addoption32(uint8 code, uint32 value){  uint8 option[6];  /* Construct the option sequence */  option[DHCPD_OPTION_CODE]   = code;  option[DHCPD_OPTION_LENGTH] = 4;  memcpy(&option[DHCPD_OPTION_DATA], &value, 4);  /* Add the option sequence to the response */  return dhcpd_addoption(option);}/**************************************************************************** * Name: dhcpd_soclet ****************************************************************************/static inline int dhcpd_socket(void){  int sockfd;#if defined(HAVE_SO_REUSEADDR) || defined(HAVE_SO_BROADCAST)  int optval;  int ret;#endif  /* Create a socket to listen for requests from DHCP clients */  sockfd = socket(PF_INET, SOCK_DGRAM, 0);  if (sockfd < 0)    {      dbg("socket failed: %d\n", errno);      return ERROR;    }  /* Configure the socket */#ifdef HAVE_SO_REUSEADDR  optval = 1;  ret = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (void*)&optval, sizeof(int));  if (ret < 0)    {      dbg("setsockopt SO_REUSEADDR failed: %d\n", errno);      close(sockfd);      return ERROR;    }#endif#ifdef HAVE_SO_BROADCAST  optval = 1;  ret = setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, (void*)&optval, sizeof(int));  if (ret < 0)    {      dbg("setsockopt SO_BROADCAST failed: %d\n", errno);      close(sockfd);      return ERROR;    }#endif  return sockfd;}/**************************************************************************** * Name: dhcpd_openresponder ****************************************************************************/static inline int dhcpd_openresponder(void){  struct sockaddr_in addr;  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;    }  /* Bind the socket to a local port. We have to use INADDRY_ANY to   * receive broadcast messages.   */  addr.sin_family      = AF_INET;  addr.sin_port        = htons(DHCP_SERVER_PORT);  addr.sin_addr.s_addr = g_state.ds_serverip;  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;}/**************************************************************************** * Name: dhcpd_initpacket ****************************************************************************/static void dhcpd_initpacket(uint8 mtype){  /* Set up the generic parts of the DHCP server message */  memset(&g_state.ds_outpacket, 0, sizeof(struct dhcpmsg_s));  g_state.ds_outpacket.op         = DHCP_REPLY;  g_state.ds_outpacket.htype      = g_state.ds_inpacket.htype;  g_state.ds_outpacket.hlen       = g_state.ds_inpacket.hlen;  memcpy(&g_state.ds_outpacket.xid, &g_state.ds_inpacket.xid, 4);  memcpy(g_state.ds_outpacket.chaddr, g_state.ds_inpacket.chaddr, 16);  if (g_state.ds_outpacket.giaddr)    {      g_state.ds_outpacket.flags  = g_state.ds_inpacket.flags;    }  else    {      g_state.ds_outpacket.flags  = 0;    }  memset(g_state.ds_outpacket.giaddr, 0, 4);  /* Add the generic options */  memcpy(g_state.ds_outpacket.options, g_magiccookie, 4);  g_state.ds_optend = &g_state.ds_outpacket.options[4]; *g_state.ds_optend = DHCP_OPTION_END;  dhcpd_addoption8(DHCP_OPTION_MSG_TYPE, mtype);  dhcpd_addoption32(DHCP_OPTION_SERVER_ID, g_state.ds_serverip);}/**************************************************************************** * Name: dhcpd_sendpacket ****************************************************************************/static int dhcpd_sendpacket(int bbroadcast){  struct sockaddr_in addr;  in_addr_t ipaddr;  int sockfd;  int len;  int ret = ERROR;  /* Determine which address to respond to (or if we need to broadcast the response) */  if (bbroadcast)    {      ipaddr = INADDR_BROADCAST;    }  else if (memcmp(g_state.ds_outpacket.ciaddr, g_anyipaddr, 4) != 0)    {      memcpy(&ipaddr, g_state.ds_outpacket.ciaddr, 4);    }  else if (g_state.ds_outpacket.flags &  HTONS(BOOTP_BROADCAST))    {      ipaddr = INADDR_BROADCAST;    }  else    {      memcpy(&ipaddr, g_state.ds_outpacket.yiaddr, 4);    }  /* Create a socket to respond to send the packet to the client.  We   * cannot re-use the listener socket because it is not bound correctly   */  sockfd = dhcpd_openresponder();  if (sockfd >= 0)    {      /* Then send the reponse to the DHCP client port at that address */      memset(&addr, 0, sizeof(struct sockaddr_in));      addr.sin_family      = AF_INET;      addr.sin_port        = HTONS(DHCP_CLIENT_PORT);      addr.sin_addr.s_addr = ipaddr;      /* Send the minimum sized packet that includes the END option */      len = (g_state.ds_optend - (uint8*)&g_state.ds_outpacket) + 1;      ret = sendto(sockfd, &g_state.ds_outpacket, len, 0,                   (struct sockaddr *)&addr, sizeof(struct sockaddr_in));      close(sockfd);    }  return ret;}/**************************************************************************** * Name: dhcpd_sendoffer ****************************************************************************/static inline int dhcpd_sendoffer(in_addr_t ipaddr, uint32 leasetime){  /* Initialize the outgoing packet */  dhcpd_initpacket(DHCPOFFER);  /* Add the address offered to the client */  memcpy(g_state.ds_outpacket.yiaddr, &ipaddr, 4);  /* Add the leasetime to the response options */  dhcpd_addoption32(DHCP_OPTION_LEASE_TIME, htonl(leasetime));

⌨️ 快捷键说明

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