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

📄 dhcpclnt.c

📁 在ARM7和UC/OSII的平台上实现了GPS自动报站的功能,涉及GPS模块LEA_4S的驱动,位置速寻算法,语音芯片ISD4004的录放音驱动,LED页面管理等等.从启动代码到操作系统的移植以及到业
💻 C
📖 第 1 页 / 共 3 页
字号:
 * 
 * PARAM1: int iface
 *
 * RETURNS: Returns 0 if ok, else non-zero ENP_ error. 
 */

int
dhc_discover(int iface)
{
   PACKET pkt;
   struct bootp * outbp;   /* pointer to bootp block in buffer to build */
   u_char * opts;       /* scratch pointer to DHCP options field */
   long     leasetime;
   int      e;

   /* get a UDP packet buffer for DHCP sending */
   pkt = udp_alloc(sizeof(struct bootp), 0);
   if (!pkt) 
      return ENP_NOMEM;
   pkt->nb_plen = sizeof(struct bootp);

   /* start a new DHCP transaction */
   dhc_states[iface].xid = xids++;
   dhc_states[iface].secs = (unsigned short)(sysuptime()/100L);

   /* set up DHCP/BOOTP header in buffer */
   outbp = (struct bootp *)pkt->nb_prot;     /* overlay bootp struct on buffer */
   e = dhc_buildheader(iface,outbp);
   if (e)
      return e;

   /* and turn it into a DHCP DISCOVER packet */
   *(long*)(&outbp->options) = RFC1084_MAGIC_COOKIE; 
   opts = &outbp->options[4];    /* encode options after cookie */
   *opts++ = DHOP_TYPE;
   *opts++ = 1;   /* length of option field */
   *opts++ = DHCP_DISCOVER;
   leasetime = -1L ;    /* ask for infinite lease */
   PUT_IP_OPT(opts, DHOP_LEASE, leasetime);

   /* if we already have an IP address, try to get it from the server */
   if (nets[iface]->n_ipaddr != 0)
   {
      ip_addr my_ip = htonl(nets[iface]->n_ipaddr);
      PUT_IP_OPT(opts, DHOP_CADDR, my_ip);
   }

   /* If there is a list of options to be requested from server, include it*/
#ifdef DHCP_REQLIST
   if ( reqlist_len > 0 )
   {
      int   i;
      *opts++ = DHOP_REQLIST ;
      *opts++ = (u_char)reqlist_len ;

      for (i=0 ; i < reqlist_len ; i++ )
         *opts++ = reqlist[i];
   }
#endif   /* DHCP_REQLIST */

   *opts++ = DHOP_END;

   /* last_tick needs to be set in case we are doing a retry. It 
    * prevents dhc_second from calling us to do another retry while 
    * we are stuck 
    */
   dhc_states[iface].last_tick = cticks;

   pkt->fhost = 0xFFFFFFFF;   /* broadcast discovery request */
   pkt->net = nets[iface];    /* send out caller spec'ed net */

   /* we need to change the DHCP state before sending to avoid a 
    * race condition with the expected reply 
    */
   if (dhc_states[iface].state != DHCS_SELECTING)
      dhc_set_state(iface, DHCS_SELECTING);

   udp_send(BOOTP_SERVER_PORT, BOOTP_CLIENT_PORT, pkt);
   dsc_discovers++;

   /* state info is the same even if udp_send() failed */
   dhc_states[iface].last_tick = cticks;     /* set this again, post udp_send */
   dhc_states[iface].tries++;

   return 0;
}


/* FUNCTION: dhc_rx_offer()
 *
 * dhc_rx_offer() - process the received DHCPOFFER Process the 
 * received DHCP-OFFER and populate dhc_states[]. Then call 
 * dhc_request() to send a request packet. 
 *
 * 
 * PARAM1: int iface
 * PARAM2: struct bootp * bp
 * PARAM3: unsigned bplen
 *
 * RETURNS: 0 if OK, else ENP_ error
 */

int
dhc_rx_offer(int iface, struct bootp * bp, unsigned bplen)
{
   u_char * opts;
   int   e;

   if (dhc_states[iface].xid != bp->xid)
      return ENP_NOT_MINE;

   opts = &bp->options[4];    /* examine options after cookie */
   e = dhc_extract_opts(iface,opts);
   if (e)   /* parse error? */
   {
      dtrap("dhcpclnt 9\n");
      return e;
   }
   if (!bp->yiaddr)  /* require an IP address */
   {
      dhc_decline(iface,bp, bplen);
      return ENP_NOT_MINE;
   }
   dhc_states[iface].ipaddr = bp->yiaddr;

   /* if we got here, we must like the offer -- send a DHCP REQUEST */
   return (dhc_request(iface,FALSE));
}


/* FUNCTION: dhc_request()
 * 
 * dhc_request() - called when 
 * 1. we have received a DHCP offer (via dhc_rx_offer() ). 
 * 2. we have to renew a lease with a DHCP server. ( via dhc_reclaim() ). 
 * 3. we have to rebind to a different DHCP server. 
 * 4. we are in INIT-REBOOT state (via dhc_reclaim() ). 
 * This should format & send a request. Values are picked from 
 * dhc_states[]. It handles the specific nuances of a REQUEST 
 * depending on the state of DHCP Client. It implements the following 
 * table of RFC2131 (sec 4.3.6). 
 * --------------------------------------------------------------------- 
 * |              |INIT-REBOOT |SELECTING |RENEWING   |REBINDING | 
 * --------------------------------------------------------------------- 
 * |broad/unicast |broadcast   |broadcast |unicast    |broadcast | 
 * |server-ip     |MUST NOT    |MUST      |MUST NOT   |MUST NOT  | 
 * |requested-ip  |MUST        |MUST      |MUST NOT   |MUST NOT  | 
 * |ciaddr        |zero        |zero      |IP address |IP address| 
 * --------------------------------------------------------------------- 
 * In a DISCOVER->OFFER->REQUEST scenario, we need to use the same 
 * XID, SECS field as in OFFER packet. This is controlled via 
 * xid_flag. If xid_flag is TRUE, then use a new XID. Else use the 
 * old one.
 *
 * PARAM1: int iface
 * PARAM2: int xid_flag
 *
 * RETURNS:  Returns 0 if ok, else non-zero ENP_ error. 
 */

int
dhc_request(int iface,int xid_flag)
{
   struct  bootp *   outbp;
   PACKET  pkt;         /* Outgoing packet */
   u_char  *   opts; /* scratch pointer to DHCP options field */
   ip_addr opt_ip;      /* IP address temporary */
   int      e;       /* error holder */

   /* get a UDP packet buffer for sending DHCP request */
   pkt = udp_alloc(sizeof(struct bootp) + DHCP_OPTSIZE - BOOTP_OPTSIZE, 0);
   if (!pkt) 
      return ENP_NOMEM;
   pkt->nb_plen = sizeof(struct bootp) - BOOTP_OPTSIZE;

   if ( xid_flag == TRUE )
   {
      dhc_states[iface].xid  = xids++;
      dhc_states[iface].secs = 0;
   }

   /* build a BOOTP request header */
   outbp = (struct bootp *)pkt->nb_prot;
   e     = dhc_buildheader(iface,outbp);
   if (e)
      return e;

   /* turn it into a DHCP REQUEST packet */
   *(long*)(&outbp->options) = RFC1084_MAGIC_COOKIE; 
   opts    = &outbp->options[4];    /* encode options after cookie */
   *opts++ = DHOP_TYPE;
   *opts++ = 1;   /* length of option field */
   *opts++ = DHCP_REQUEST;

   /* append the options that we want to request */
   if ((dhc_states[iface].state == DHCS_SELECTING) ||
       (dhc_states[iface].state == DHCS_REQUESTING) ||
       (dhc_states[iface].state == DHCS_REBOOTING) ||
       (dhc_states[iface].state == DHCS_INITREBOOT))
   {
      opt_ip = ntohl(dhc_states[iface].ipaddr);
      PUT_IP_OPT(opts, DHOP_CADDR, opt_ip);
   }
   if (dhc_states[iface].snmask)
   {
      opt_ip = ntohl(dhc_states[iface].snmask);
      PUT_IP_OPT(opts, DHOP_SNMASK, opt_ip);
   }
   if (dhc_states[iface].defgw)
   {
      opt_ip = ntohl(dhc_states[iface].defgw);
      PUT_IP_OPT(opts, DHOP_ROUTER, opt_ip);
   }
#if defined(DHC_MAXDNSRVS) && (DHC_MAXDNSRVS > 0)
   {
      int   i;
      u_char * optlen;
      for (i = 0; i < DHC_MAXDNSRVS; i++)
      {
         if (dhc_states[iface].dnsrv[i])
         {
            if (i == 0)
            {
               *opts++ = DHOP_DNSRV;
               optlen  = opts;
               *opts++ = 0;
            }
            /* Copy the IP address in nw byte order */
            opt_ip = dhc_states[iface].dnsrv[i];
            MEMCPY((char *)opts, (char *)&opt_ip,4);
            opts+=4;
            *optlen += 4;
         }
      }
   }
#endif

   if (dhc_states[iface].lease)
   {
      PUT_IP_OPT(opts, DHOP_LEASE, dhc_states[iface].lease);
   }

   /* If there is a list of options to be requested from server, include it*/
#ifdef DHCP_REQLIST
   if ( reqlist_len > 0 )
   {
      int   i;
      *opts++ = DHOP_REQLIST ;
      *opts++ = (u_char)reqlist_len ;

      for (i=0 ; i < reqlist_len ; i++ )
         *opts++ = reqlist[i];
   }
#endif   /* DHCP_REQLIST */

   /* only set client IP address (ours) when renewing or rebinding */
   if ((dhc_states[iface].state == DHCS_RENEWING)
       || (dhc_states[iface].state == DHCS_REBINDING))
   {
      outbp->ciaddr = nets[iface]->n_ipaddr;
   }

   /* RFC 2131, section 4.3.5 ref to server-ip is option 54 0x36, not 
    * siaddr: p. 16 number 3: "The client broadcasts a DHCPREQUEST 
    * message that MUST include the 'server identifier' option to 
    * indicate which server it has selected. . . ." p. 31 bullet 1: 
    * "Client inserts the address of the selected server in 'server 
    * identifier'. . . ." RFC 951, p. 4 definition of 'siaddr' is 
    * "server IP address; returned in bootreply by server." 
    */
   /* Only include server identifier option when selecting a server. */
   if ((dhc_states[iface].state == DHCS_SELECTING) ||
       (dhc_states[iface].state == DHCS_REQUESTING))
   {
      opt_ip = ntohl(dhc_states[iface].srv_ipaddr);
      PUT_IP_OPT(opts, DHOP_SERVER, opt_ip);
   }

#ifdef USE_AUTOIP
   /* add hostname (code 12) */
   PUT_STRING_OPT(opts, 12, dhc_hostname()); 
#endif /* USE_AUTOIP */

   *opts++ = DHOP_END;  /* Mark the end of options */

   /* figure out whether to send via unicast or broadcast */
   if (dhc_states[iface].state == DHCS_RENEWING)
   {
      pkt->fhost = dhc_states[iface].srv_ipaddr;
   }
   else
   {
      pkt->fhost = 0xFFFFFFFF;   /* broadcast request */
   }

   pkt->net = nets[iface];    /* send out caller spec'ed net */
   pkt->nb_plen = (char *)opts - (char *)outbp;
   udp_send(BOOTP_SERVER_PORT, BOOTP_CLIENT_PORT, pkt);
   dsc_requests++;

   dhc_states[iface].last_tick = cticks;
   dhc_states[iface].tries++;

   return 0;   /* return OK code */
}


#ifdef MINI_IP

/* FUNCTION: fixup_subnet_mask()
 *
 * This is a workalike to the function of the same name in the ip directory.
 * If we are using MINI_IP then dhcp needs it's own copy of this.
 * 
 * PARAM1: int netnum
 *
 * RETURNS: 
 */

void
fixup_subnet_mask(int netnum)      /* which of the nets[] to do. */
{
   u_long   smask;

   if (m_netp->snmask)  /* if mask is already set, don't bother */
      return;

   /* things depending on IP address class: */
   if ((m_netp->n_ipaddr & AMASK) == AADDR)
      smask = 0xFF000000L;
   else if((m_netp->n_ipaddr & BMASK) == BADDR)
      smask = 0xFFFF0000L;
   else if((m_netp->n_ipaddr & CMASK) == CADDR)
      smask = 0xFFFFFF00L;
   else
   {
      dtrap("dhcpclnt 10\n");    /* bad logic or setup values */
      smask = 0xFFFFFF00L;
   }
   m_netp->snmask = htonl(smask);
}
#endif /* MINI_IP */


/* FUNCTION: dhc_setip()
 *
 * dhc_setip() : Set the IP address (& other paras) for the interface 
 * It is called when we have received an ACK. That is, we have the IP 
 * address and other information needed for this interface. If the 
 * subnet mask has not been specified by the DHCP Server, then we 
 * will calculate one from the IP Address using fixup_subnet_mask() 
 * 
 * PARAM1: int iface
 *
 * RETURNS: Returns 0 if ok, else non-zero ENP error.
 */

int
dhc_setip(int iface)
{
   nets[iface]->n_ipaddr = dhc_states[iface].ipaddr;
   nets[iface]->snmask   = dhc_states[iface].snmask;
   nets[iface]->n_defgw  = dhc_states[iface].defgw;

   if ( nets[iface]->snmask == 0 )
   {
      fixup_subnet_mask(iface);
      dhc_states[iface].snmask = nets[iface]->snmask; 
   }

   /* fixup broadcast addresses */
   nets[iface]->n_netbr    = nets[iface]->n_ipaddr | ~nets[iface]->snmask;
   nets[iface]->n_netbr42  = nets[iface]->n_ipaddr &  nets[iface]->snmask;
   nets[iface]->n_subnetbr = nets[iface]->n_ipaddr | ~nets[iface]->snmask;

   return 0;   /* return OK code */
}


/* FUNCTION: dhc_resetip()
 *
 * dhc_resetip() : Reset the IP address (& other paras) for the 
 * interface It is called when we didn't receive a ACK/NAK for the 
 * interface when RENEWING/REBINDING. 
 * 
 * PARAM1: int iface
 *
 * RETURNS: Returns 0 if ok, else non-zero error. 
 */

int
dhc_resetip(int iface)
{
   /* reset the ipaddress */
   nets[iface]->n_ipaddr = 0;
   nets[iface]->snmask   = 0;
   nets[iface]->n_defgw  = 0;

   /* reset the broadcast addresses */
   nets[iface]->n_netbr    = 0;
   nets[iface]->n_netbr42  = 0;
   nets[iface]->n_subnetbr = 0;

   return 0;   /* return OK code */
}



/* FUNCTION: dhc_decline()
 * 
 * dhc_decline() - send a decline packet to server. This is usually 
 * because he didn't send us an IP address. 
 *
 * PARAM1: int iface
 * PARAM2: struct bootp * bp
 * PARAM3: unsigned bplen
 *
 * RETURNS: Returns 0 if ok, else non-zero ENP_ error. 
 */

int
dhc_decline(int iface,struct bootp * bp, unsigned bplen)
{
   struct bootp * outbp;
   PACKET pkt;
   u_char * opts;    /* scratch pointer to DHCP options field */

   /* get a UDP packet buffer for sending DHCP */
   pkt = udp_alloc(bplen, 0);
   if (!pkt) 
      return ENP_NOMEM;
   pkt->nb_plen = bplen;

   outbp = (struct bootp *)pkt->nb_prot;
   MEMCPY(outbp, bp, bplen);
   outbp->op = BOOTREPLY;

   /* find DHCP TYPE option so we can overwrite it */   
   opts = find_opt(DHOP_TYPE, &outbp->options[4]);
   opts += 2;     /* point to actual op code */
   *opts = DHCP_DECLINE;   /* overwrite op code */

   pkt->fhost = 0xFFFFFFFF;   /* broadcast decline pkt */
   pkt->net = nets[iface];    /* send out caller speced net */
   udp_send(BOOTP_SERVER_PORT, BOOTP_CLIENT_PORT, pkt);
   dsc_declines++;   /* count declines sent */
   return 0;
}



/* FUNCTION: dh_getlong()
 *
 * dh_getlong() - routine to extract a 'long' from an arbitrary 
 * address NB: value is expected to remain in network byte order! 
 *
 * 
 * PARAM1:  u_char *ptr 
 *
 * RETURNS: the extracted 32 bit value
 */

static   long dh_getlong( u_char *ptr )
{
     long  v;
     u_char * p2 =  (u_char *)&v;

   *p2++ = *ptr++;
   *p2++ = *ptr++;
   *p2++ = *ptr++;
   *p2++ = *ptr++;

   return v;
}


/* FUNCTION: dhc_extract_opts()
 * 
 * dhc_extract_opts() - extract certain interesting options from the 
 * options string passed. These options are filled in to the fields 
 * passed. 
 *
 * PARAM1: int iface
 * PARAM2: u_char * opts
 *
 * RETURNS: Returns 0 if opts string was parsed OK, else non-zero if 
 * there was a parse error. 0 return doesn't mean all (or even any) 
 * of the options passed were filled in with good values. 
 */

int
dhc_extract_opts(int iface,u_char * opts)
{
   u_char * end   =  opts  +  DHCP_OPTSIZE;  /* limit scope of search */
   u_char   optlen;
#if defined(DHC_MAXDNSRVS) && (DHC_MAXDNSRVS > 0)

⌨️ 快捷键说明

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