📄 tftp.c
字号:
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, ð, 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 + -