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

📄 tftp.c

📁 开放源码的编译器open watcom 1.6.0版的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
    free (sock);
    sock = NULL;
  }
  if (inbuf)
     free (inbuf);
  if (outbuf)
     free (outbuf);
  inbuf = outbuf = NULL;
}


/*
 * Set the name of TFTP server
 */
char *tftp_set_server (const char *name, int len)
{
  len = min (len, sizeof(tftp_server_name)-1);
  memcpy (tftp_server_name, name, len);
  tftp_server_name[len] = 0;
  return (tftp_server_name);
}

/*
 * Set the name of file to load from TFTP server
 */
char *tftp_set_boot_fname (const char *name, int len)
{
  len = min (len, sizeof(tftp_boot_fname)-1);
  memcpy (tftp_boot_fname, name, len);
  tftp_boot_fname[len] = 0;
  return (tftp_boot_fname);
}

/*
 * Set the mode used for transfer
 */
char *tftp_set_xfer_mode (const char *name, int len)
{
  len = min (len, sizeof(tftp_xfer_mode)-1);
  memcpy (tftp_xfer_mode, name, len);
  tftp_xfer_mode[len] = 0;
  return (tftp_xfer_mode);
}

/*
 * Read the next data packet from a TFTP connection
 */
static int tftp_get (char **buf)
{
  int retry;

  /* Don't do anything if no TFTP connection is active.
   */
  if (!isopen)
     return (0);

  /* If the block number is 0 then we are still dealing with the first
   * data block after opening a connection. If the data size is smaller
   * than 'blocksize' just close the connection again.
   */
  if (currblock == 0)
  {
    currblock++;
    if (ibuflen < blocksize)
       isopen = FALSE;
    *buf = &inbuf->th_data[0];
    return (ibuflen);
  }

  /* Wait for the next data packet. If no data packet is coming in,
   * resend the ACK for the last packet to restart the sender. Maybe
   * he didn't get our first ACK.
   */
  for (retry = 0; retry < tftp_retry; retry++)
  {
    if (debug_on)
       (*_outch) ('.');

    ibuflen = recv_packet (currblock+1);
    if (ibuflen >= 0)
    {
      currblock++;
      send_ack (currblock);
      if (ibuflen < blocksize)  /* last block received */
         isopen = FALSE;
      *buf = &inbuf->th_data[0];
      return (ibuflen);
    }
    if (tftp_errno == ERR_ERR || tftp_errno == ERR_UNKNOWN)
       break;

    send_ack (currblock);
  }
  isopen = FALSE;
  return (-1);
}

/*
 * Load the BOOT-file from TFTP server
 */
int tftp_boot_load (void)
{
  int rc = 0;

  /* Allocate socket and buffers
   */
  sock   = malloc (sizeof(sock->udp));
  inbuf  = malloc (TFTP_HEADSIZE+SEGSIZE);
  outbuf = malloc (TFTP_HEADSIZE+SEGSIZE);

  if (!sock || !inbuf || !outbuf)
  {
    outsnl (_LANG("No memory for TFTP boot."));
    return (0);
  }

  if (!tftp_boot_fname[0])
  {
    outsnl (_LANG("No TFTP boot filename defined."));
    return (0);
  }

  if (tftp_server_name[0] && !tftp_server)
  {
    tftp_server = resolve (tftp_server_name);
    outs (_LANG("Cannot resolve TFTP-server "));
    outsnl (tftp_server_name);
    return (0);
  }

  if (!tftp_server)
  {
    outsnl (_LANG("No TFTP-server defined."));
    return (0);
  }

  if (debug_on)
     outs (_LANG("Doing TFTP boot load..."));

  /* Open connection and request file
   */
  if (!tftp_open (tftp_server, tftp_boot_fname))
     return (0);

  while (1)
  {
    char *buf;
    int   size = tftp_get (&buf);

    if (size < 0)  /* error in transfer */
       break;

    if (size > 0 && (*tftp_writer)(buf,size) <= 0)
    {
      rc = -1;     /* writer failed, errno set */
      break;
    }
    if (size < blocksize)    /* got last block */
    {
      rc = 1;
      break;
    }
  }
  tftp_close();
  return (rc);
}


/*
 * Config-file handler for TFTP-client
 */
static void (*prev_hook) (const char*, const char*) = NULL;

static void tftp_cfg_hook (const char *name, const char *value)
{
  static struct config_table tftp_cfg[] = {
                { "BOOT_FILE", ARG_FUNC,    (void*)tftp_set_boot_fname },
                { "SERVER",    ARG_RESOLVE, (void*)&tftp_server        },
                { "TIMEOUT",   ARG_ATOI,    (void*)&tftp_timeout       },
                { "RETRY",     ARG_ATOI,    (void*)&tftp_retry         },
                { "MODE",      ARG_FUNC,    (void*)tftp_set_xfer_mode  },
                { "PORT",      ARG_ATOI,    (void*)&tftp_lport         },
                { NULL }
              };
  if (!parse_config_table(tftp_cfg, "TFTP.", name, value) && prev_hook)
     (*prev_hook) (name, value);
}

/*
 * Initialize config-hook for TFTP protocol.
 */ 
int tftp_init (void)
{
  prev_hook = usr_init;
  usr_init  = tftp_cfg_hook;
  return (TRUE);
}

/*
 * A small test program, for djgpp/Watcom only
 */
#if defined(TEST_PROG) 

#include "getopt.h"
#include "udp_nds.h"
#include "pcdbug.h"
#include "pcbsd.h"
#include "pcarp.h"

extern unsigned int sleep (unsigned int);

static FILE *file;
static char *fname;

static int write_func (const void *buf, size_t length)
{
  static int block = 0;

  debug_on = 2;

  if (block == 0)
  {
    fname = tftp_boot_fname;  /* !!to-do: map into local filesystem */
    fprintf (stderr, "opening `%s'\n", fname);
    file = fopen (fname, "wb");
  }
  if (!file)
  {
    perror (fname);
    return (0);
  }
  fwrite (buf, 1, length, file);
  return (++block);
}

int close_func (void)
{
  if (file && fname)
  {
    fprintf (stderr, "closing `%s'\n", fname);
    fclose (file);
    file = NULL;
    return (1);
  }
  return (0);
}

void usage (char *argv0)
{
  char buf1[20], buf2[20], *env = getenv (_watt_environ_name);

  printf ("Usage: %s [[-n] [-a] [-h host] [-f file]\n"
          "\t\t [-i ip] [-m mask]] [-t timeout] [-r retry]\n"
          "\t -n run with no config file (default %s\\%s)\n"
          "\t -a add random MAC address for tftp host\n"
          "\t -h specify tftp host\n"
          "\t -f specify file to load\n"
          "\t -i specify ip-address      (default %s)\n"
          "\t -m specify network mask    (default %s)\n"
          "\t -t specify total timeout   (default %d)\n"
          "\t -r specify retry count     (default %d)\n",
          argv0, env ? env : ".", _watt_config_name,
          _inet_ntoa(buf1,my_ip_addr),
          _inet_ntoa(buf2,sin_mask),
          tftp_timeout, tftp_retry);
  exit (-1);
}

int main (int argc, char **argv)
{
  eth_address eth = { 1,2,3,4,5,6 };
  int a_flag = 0;
  int h_flag = 0;
  int i_flag = 0;
  int f_flag = 0;
  int n_flag = 0;
  int m_flag = 0;
  int ch;

  while ((ch = getopt(argc, argv, "an?h:i:f:m:t:r:")) != EOF)
     switch (ch)
     {
       case 'a':
            a_flag = 1;
            break;
       case 'n':        
            n_flag = 1;
            break;
       case 'h':
            h_flag = 1;
            tftp_server = aton (optarg);
            break;
       case 'i':
            i_flag = 1;
            my_ip_addr = aton (optarg);
            break;
       case 'f':
            f_flag = 1;
            tftp_set_boot_fname (optarg, strlen(optarg));
            break;
       case 'm':
            m_flag = 1;
            sin_mask = aton (optarg);
            break;
       case 't':
            tftp_timeout = atoi (optarg);
            break;
       case 'r':
            tftp_retry = atoi (optarg);
            break;
       case '?':
       default:
            usage (argv[0]);
     }

  if (n_flag)  /* Demonstrate running with no config file */
  {
    _watt_no_config = 1;
    dbg_mode_all    = 1;
    dbg_print_stat  = 1;
    debug_on = 2;

    if (!m_flag)  sin_mask    = aton ("255.255.0.0");
    if (!i_flag)  my_ip_addr  = aton ("192.168.0.1");
    if (!h_flag)  tftp_server = aton ("192.168.0.2");
    if (!f_flag)  tftp_set_boot_fname ("test", 4);
    if (a_flag)  _arp_add_cache (tftp_server, &eth, 0);
  }
  else if (m_flag || i_flag || h_flag || f_flag || a_flag)
  {
    puts ("Cannot use this option without -n flag");
    return (-1);
  }

  dbug_init();
  if (n_flag)
     dbug_open();

  /* Must set our hook first
   */
  tftp_writer     = write_func;
  tftp_terminator = close_func;

  sock_init();

  sleep (1);       /* drain network buffers */
  tcp_tick (NULL);
  return (0);
}
#endif /* TEST_PROG */
#endif /* USE_TFTP */

⌨️ 快捷键说明

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