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

📄 pcdhcp.c

📁 开放源码的编译器open watcom 1.6.0版的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
             char *p = tftp_set_boot_fname ((const char*)(opt+2), opt[1]);
             TRACE ("BOOT-file: `%s'\r\n", p);
           }
           break;
#endif

      case END_OPT:
           TRACE ("got end-option\r\n", 0);
           return (got_offer);

      default:
           TRACE ("Ignoring option %d\r\n", *opt);
           break;
    }
    opt += *(opt+1) + 2;
  }

  if (extra_options.data)
  {
    struct dhcp ext;

    len = min (extra_options.size, sizeof(ext.dh_opt));
    extra_options.data [len] = END_OPT;
    memcpy (ext.dh_opt, extra_options.data, len);
    DHCP_offer (&ext);
  }
  return (got_offer);
}

/*-------------------------------------------------------------------*/

static int DHCP_ack (struct dhcp *in)
{
  BYTE *opt = (BYTE*) &in->dh_opt[4];

  return (opt[0] == DHCP_MSG_TYPE && opt[1] == 1 && opt[2] == DHCP_ACK);
}

/*-------------------------------------------------------------------*/

static int DHCP_nack (struct dhcp *in)
{
  BYTE *opt = (BYTE*) &in->dh_opt[4];

  return (opt[0] == DHCP_MSG_TYPE && opt[1] == 1 && opt[2] == DHCP_NAK);
}

/*-------------------------------------------------------------------*/

void DHCP_release (void)
{
  struct udp_Socket socket;
  struct dhcp       dhcp_out;

  if (!configured)
     return;

#if 0 /* !!to-do: if DHCP-config is saved on disk, use that next time */
  if (DHCP_remaining_lease() > 10)
     return;

  set_config ("dhcp_iplease", 0);
#endif

  TRACE ("Sending DHCP release\r\n", 0);  /* release is unicast */

  udp_open (&socket, IPPORT_BOOTPC, dhcp_server, IPPORT_BOOTPS, NULL);
  sock = (sock_type*) &socket;

  DHCP_release_decline (&dhcp_out, DHCP_RELEASE, NULL);
  sock_close (sock);
}

/*-------------------------------------------------------------------*/

static sock_type *dhcp_open (int reconf)
{
  static udp_Socket socket;
  DWORD  host;

  outs (reconf ? _LANG("Reconfiguring through DHCP..")
               : _LANG("Configuring through DHCP..."));

  if (bcast_on)
       host = (DWORD)-1;
  else host = dhcp_server;

  udp_open (&socket, IPPORT_BOOTPC, host, IPPORT_BOOTPS, NULL);
  return (sock_type*)&socket;
}

/*-------------------------------------------------------------------*/

static void arp_add_server (sock_type *sock)
{
  if ((_pktdevclass == PD_ETHER || _pktdevclass == PD_TOKEN) &&
      memcmp(&sock->udp.hisethaddr, &_eth_brdcast, sizeof(_eth_brdcast)))
    _arp_add_cache (dhcp_server, &sock->udp.hisethaddr, TRUE);
}

/*
 * _dodhcp() - our first time (booting) DHCP handler.
 * Doesn't hurt that it's blocking, but should be rewitten together
 * with dhcp_renew() to make a proper state machine.
 */
int _dodhcp (void)
{
  struct dhcp dhcp_out;
  struct dhcp dhcp_in;
  int    status, loop, len;
  int    save_mtu = mtu;

  mtu        = ETH_MAX_DATA;
  sock       = dhcp_open (0);
  start_time = time (NULL);

  for (loop = 0; loop < max_retries; loop++)
  {
    DWORD sendtimeout;

    TRACE ("Sending DHCP discover (%d)\r\n", loop);

    if (!DHCP_discover (&dhcp_out))
       goto sock_exit;

    sendtimeout = set_timeout (dhcp_timeout * 1000);

    while (!chk_timeout(sendtimeout))
    { 
      sock_tick (sock, &status);
      if (!sock_dataready(sock))
         continue;

      len = sock_fastread (sock, (BYTE*)&dhcp_in, sizeof(dhcp_in));

      if (len < DHCP_MIN_SIZE ||              /* too short packet */
          dhcp_in.dh_op  != BOOTREPLY ||      /* not a BOOT reply */
          dhcp_in.dh_xid != dhcp_out.dh_xid)  /* not our exchange ID */
         continue;
     
      gateway = dhcp_in.dh_giaddr;

      if (!got_offer && DHCP_offer(&dhcp_in))
      {
        TRACE ("Got DHCP offer\r\n", 0);
        RandomWait (1000, 2000);

        if (dhcp_iplease == 0L)                  /* cannot happen ? */
            dhcp_iplease = 3600L;
        if (dhcp_renewal == 0L)
            dhcp_renewal = dhcp_iplease / 2;     /* default T1 time */
        if (dhcp_rebind == 0)
            dhcp_rebind = dhcp_iplease * 7 / 8;  /* default T2 time */

        TRACE ("Sending DHCP request\r\n", 0);
        DHCP_request (&dhcp_out, renewing, dhcp_in.dh_yiaddr);

        /* Remember my_ip_addr from OFFER because WinNT server
         * doesn't include it in ACK message.
         */
        my_ip_addr = ((udp_Socket*)sock)->myaddr = intel (dhcp_in.dh_yiaddr);
        TRACE ("my_ip_addr = %s\r\n", INET_NTOA(my_ip_addr));

        sendtimeout = set_timeout (10000);
        continue;
      }

      if (DHCP_ack(&dhcp_in))
      {
        if (!DHCP_process_ack(&dhcp_out))
           continue;

        dhcp_set_timers();
        addwattcpd (dhcp_daemon);
#if 0
       /* !!to-do: save DHCP-config to disk (temp-file) for use next
        *          time we boot. Hence no need to do all this each time
        */
#endif
        goto sock_exit;    /* OK return */
      }
      if (DHCP_nack(&dhcp_in))
      {
        TRACE ("Got DHCP nack\r\n", 0);
        my_ip_addr = 0;
        break;          /* retry */
      }

      memset (&dhcp_in, 0, sizeof(dhcp_in));
      continue;
    }
  }

sock_exit:
sock_err:

  if (dhcp_server)
     arp_add_server (sock);

  sock_close (sock);
  dhcp_options_free();

  mtu = save_mtu;
  return (my_ip_addr != 0);
}

/*
 * dhcp_renew() - enter renewing or rebinding state
 * !! to-do: make this a non-blocking state-machine.
 */
static int dhcp_renew (void)  
{
  struct dhcp dhcp_out;
  struct dhcp dhcp_in;
  int    status, loop, len;

  sock       = dhcp_open (1);
  start_time = time (NULL);

  for (loop = 0; loop < max_retries; loop++)
  {
    DWORD sendtimeout;

    TRACE ("Sending DHCP request\r\n", 0);
    if (!DHCP_request (&dhcp_out, renewing, intel(my_ip_addr)))
       goto sock_exit;

    sendtimeout = set_timeout (dhcp_timeout * 1000);

    while (!chk_timeout(sendtimeout))
    {
      sock_tick (sock, &status);
      if (!sock_dataready(sock))
         continue;

      len = sock_fastread (sock, (BYTE*)&dhcp_in, sizeof(dhcp_in));

      if (len < DHCP_MIN_SIZE ||              /* too short packet */
          dhcp_in.dh_op  != BOOTREPLY ||      /* not a BOOT reply */
          dhcp_in.dh_xid != dhcp_out.dh_xid)  /* not our exchange ID */
         continue;
     
      gateway = dhcp_in.dh_giaddr;
      if (DHCP_ack(&dhcp_in))
      {
        if (!DHCP_process_ack(&dhcp_out))
           continue;

        dhcp_set_timers();
        addwattcpd (dhcp_daemon);
        goto sock_exit;           /* OK return */
      }
      if (DHCP_nack(&dhcp_in))
      {
        TRACE ("Got DHCP nack\r\n", 0);
        my_ip_addr = 0;
        break;          /* retry */
      }
      memset (&dhcp_in, 0, sizeof(dhcp_in));
      continue;
    }
  }

sock_exit:
sock_err:
  sock_close (sock);
  return (my_ip_addr != 0);
}

/*-------------------------------------------------------------------*/

static void dhcp_option_add (BYTE *opt, int max)
{
  int   len = 0;
  char *add;

  extra_options.data = realloc (extra_options.data, max);
  if (!extra_options.data)
     return;

  add = (char*)&extra_options.data + extra_options.size;

  /* Loop over `opt' and append to `add'. Strip away END_OPT
   * and PAD_OPT options.
   */
  while (opt < opt + max)
  {
    if (*opt == PAD_OPT)
       continue;
    if (*opt == END_OPT)
       return;

    len = opt[1];
    memcpy (add, opt, len+2);
    add += len + 2;
    opt += len + 2;
    extra_options.size += len + 2;
  }
}

/*-------------------------------------------------------------------*/

static void dhcp_options_free (void)
{
  if (extra_options.data)
  {
    free (extra_options.data);
    extra_options.data = NULL;
    extra_options.size = 0;
  }
}

/*-------------------------------------------------------------------*/

void _dodhcp_inform (void)
{
  struct dhcp dhcp_out;
  struct dhcp dhcp_in;
  udp_Socket  socket;
  int         status, len;
  DWORD       sendtimeout;

  if (!do_inform || !dhcp_server)
     return;
 
  udp_open (&socket, IPPORT_BOOTPC, dhcp_server, IPPORT_BOOTPS, NULL);
  sock       = (sock_type*) &socket;
  start_time = time (NULL);

  if (trace_on || debug_on)
     outs (_LANG("Sending DHCP inform.."));

  DHCP_inform (&dhcp_out);
  sendtimeout = set_timeout (dhcp_timeout * 1000);

  while (!chk_timeout(sendtimeout))
  {
    sock_tick (sock, &status);
    if (!sock_dataready(sock))
       continue;

    len = sock_fastread (sock, (BYTE*)&dhcp_in, sizeof(dhcp_in));

    if (len < DHCP_MIN_SIZE ||              /* too short packet */
        dhcp_in.dh_op  != BOOTREPLY ||      /* not a BOOT reply */
        dhcp_in.dh_xid != dhcp_out.dh_xid)  /* not our exchange ID */
       continue;

    if (DHCP_ack(&dhcp_in))
       break;
  }

sock_err:
  sock_close (sock);
  if (chk_timeout(sendtimeout))
       TRACE ("Got no DHCP ack\r\n", 0);
  else TRACE ("Got DHCP ack\r\n", 0);
}

/*-------------------------------------------------------------------*/

static void dhcp_set_timers (void)
{
  check_timer   = set_timeout (1000); /* count down each sec */
  renewal_count = (long)dhcp_renewal;
  rebind_count  = (long)dhcp_rebind;
  if (rebind_count == renewal_count)
      rebind_count += 10;             /* add 10 seconds */
}

/*
 * dhcp_daemon() - called from tcp_tick()
 */
static void dhcp_daemon (void) 
{
  BOOL t1, t2;

  if (!chk_timeout(check_timer))
     return;

  check_timer = set_timeout (1000);
  t1 = (--renewal_count <= 0);
  t2 = (--rebind_count  <= 0);

  if (!t1 && !t2)
     return;

  renewing = 1;
  bcast_on = 0;              /* can Unicast now       */
  if (t1) gateway  = 0;      /* don't use relay agent */
  if (t2) bcast_on = 1;      /* must use Broadcast    */

  TRACE ("DHCP daemon timeout: %s\r\n", t1 ? "RENEWAL" : "REBIND");

  suggestLease = dhcp_iplease;
  delwattcpd (dhcp_daemon);  /* don't run daemon now */
  dhcp_renew();
}

/*
 * Parse a list of DHCP-request options from config-file.
 * e.g DHCP_REQ_LIST = 1,23,24,28,36
 */
static int set_request_list (char *options)
{
  static int init = 0;
  int    num      = 0;
  int    maxreq   = 312 - 27; /* sizeof(dh_opt) - min size of rest */
  BYTE  *list, *start, *tok, *end;

  if (init || (list = calloc(maxreq,1)) == NULL)
     return (0);

  init  = 1;
  start = list;
  end   = start + maxreq - 1;
  tok   = (BYTE*) strtok (options, ", \t");

  while (tok && list < end)
  {
    *list = atoi ((const char*)tok);
    tok   = (BYTE*) strtok (NULL, ", \t");

    /* If request list start with Pad option ("DHCP.REQ_LIST=0"),
     * disable options all-together.
     */
    if (num == 0 && *list == '0')
       break;
    num++;
    list++;
  }

  request_list.data = start;
  request_list.size = num;

#if 0  /* test */
  {
    int i;
    for (i = 0; i < request_list.size; i++)
        printf ("%2d, ", request_list.data[i]);
    puts ("");
  }
#endif
  return (1);
}

static BYTE *put_request_list (BYTE *opt, int filled)
{
  struct dhcp dhcp;
  int    size = min (request_list.size, sizeof(dhcp.dh_opt)-filled-1);
                                               /* room for END_OPT ^ */
  if (size > 0 && request_list.data)
  {
    *opt++ = DHCP_PARAM_REQUEST;
    *opt++ = request_list.size;
    memcpy (opt, request_list.data, size);
    opt += size;
  }
  return (opt);
}

/*-------------------------------------------------------------------*/

static void (*prev_hook) (const char*, const char*) = NULL;

static void DHCP_config (const char *name, const char *value)
{
  static struct config_table dhcp_cfg[] = {
                { "REQ_LIST", ARG_FUNC,   (void*)set_request_list },
                { "TRACE",    ARG_ATOI,   (void*)&trace_on        },
                { "BCAST",    ARG_ATOI,   (void*)&bcast_flag      },
                { "INFORM",   ARG_ATOI,   (void*)&do_inform       },
                { "TIMEOUT",  ARG_ATOI,   (void*)&dhcp_timeout    },
                { "RETRIES",  ARG_ATOI,   (void*)&max_retries     },
                { "ARPCHECK", ARG_ATOI,   (void*)&arp_check_ip    },
                { "HOST",     ARG_RESOLVE,(void*)&dhcp_server     },
                { NULL }
              };

  if (!parse_config_table(&dhcp_cfg[0], "DHCP.", name, value) && prev_hook)
     (*prev_hook) (name, value);
}

void DHCP_init (void)
{
  prev_hook = usr_init;
  usr_init  = DHCP_config;
}

#endif /* USE_DHCP */

⌨️ 快捷键说明

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