forked from mirrors/tftp-hpa-google
Add support for IPv6 in the server and client.
Add support for IPv6 in the server and client. You can force the use of IPv4 or IPv6 only with new -4 and -6 commandline options, if IPv6 support was compiled in. Signed-off-by: Karsten Keil <kkeil@suse.de> Signed-off-by: H. Peter Anvin <hpa@zytor.com>
This commit is contained in:
parent
7fe0fb941c
commit
28f22b6591
9 changed files with 574 additions and 185 deletions
135
tftp/main.c
135
tftp/main.c
|
@ -40,7 +40,6 @@
|
|||
*/
|
||||
#include <sys/file.h>
|
||||
#include <ctype.h>
|
||||
#include <netdb.h>
|
||||
#ifdef WITH_READLINE
|
||||
#include <readline/readline.h>
|
||||
#ifdef HAVE_READLINE_HISTORY_H
|
||||
|
@ -72,8 +71,16 @@ static const struct modes modes[] = {
|
|||
#define MODE_NETASCII (&modes[0])
|
||||
#define MODE_DEFAULT MODE_NETASCII
|
||||
|
||||
struct sockaddr_in peeraddr;
|
||||
int f;
|
||||
#ifdef HAVE_IPV6
|
||||
int ai_fam = AF_UNSPEC;
|
||||
int ai_fam_sock = AF_UNSPEC;
|
||||
#else
|
||||
int ai_fam = AF_INET;
|
||||
int ai_fam_sock = AF_INET;
|
||||
#endif
|
||||
|
||||
union sock_addr peeraddr;
|
||||
int f = -1;
|
||||
u_short port;
|
||||
int trace;
|
||||
int verbose;
|
||||
|
@ -184,14 +191,18 @@ const char *program;
|
|||
static inline void usage(int errcode)
|
||||
{
|
||||
fprintf(stderr,
|
||||
#ifdef HAVE_IPV6
|
||||
"Usage: %s [-4][-6][-v][-l][-m mode] [host [port]] [-c command]\n",
|
||||
#else
|
||||
"Usage: %s [-v][-l][-m mode] [host [port]] [-c command]\n",
|
||||
#endif
|
||||
program);
|
||||
exit(errcode);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct sockaddr_in s_in;
|
||||
union sock_addr sa;
|
||||
int arg;
|
||||
static int pargc, peerargc;
|
||||
static int iscmd = 0;
|
||||
|
@ -210,6 +221,14 @@ int main(int argc, char *argv[])
|
|||
if (argv[arg][0] == '-') {
|
||||
for (optx = &argv[arg][1]; *optx; optx++) {
|
||||
switch (*optx) {
|
||||
#ifdef HAVE_IPV6
|
||||
case '4':
|
||||
ai_fam = AF_INET;
|
||||
break;
|
||||
case '6':
|
||||
ai_fam = AF_INET6;
|
||||
break;
|
||||
#endif
|
||||
case 'v':
|
||||
verbose = 1;
|
||||
break;
|
||||
|
@ -268,6 +287,8 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
}
|
||||
|
||||
ai_fam_sock = ai_fam;
|
||||
|
||||
pargv = argv + arg;
|
||||
pargc = argc - arg;
|
||||
|
||||
|
@ -283,18 +304,7 @@ int main(int argc, char *argv[])
|
|||
sp->s_port = htons(IPPORT_TFTP);
|
||||
sp->s_proto = (char *)"udp";
|
||||
}
|
||||
port = sp->s_port; /* Default port */
|
||||
f = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (f < 0) {
|
||||
perror("tftp: socket");
|
||||
exit(EX_OSERR);
|
||||
}
|
||||
bzero((char *)&s_in, sizeof(s_in));
|
||||
s_in.sin_family = AF_INET;
|
||||
if (pick_port_bind(f, &s_in, portrange_from, portrange_to)) {
|
||||
perror("tftp: bind");
|
||||
exit(EX_OSERR);
|
||||
}
|
||||
|
||||
bsd_signal(SIGINT, intr);
|
||||
|
||||
if (peerargc) {
|
||||
|
@ -304,6 +314,21 @@ int main(int argc, char *argv[])
|
|||
setpeer(peerargc, peerargv);
|
||||
}
|
||||
|
||||
if (ai_fam_sock == AF_UNSPEC)
|
||||
ai_fam_sock = AF_INET;
|
||||
|
||||
f = socket(ai_fam_sock, SOCK_DGRAM, 0);
|
||||
if (f < 0) {
|
||||
perror("tftp: socket");
|
||||
exit(EX_OSERR);
|
||||
}
|
||||
bzero(&sa, sizeof(sa));
|
||||
sa.sa.sa_family = ai_fam_sock;
|
||||
if (pick_port_bind(f, &sa, portrange_from, portrange_to)) {
|
||||
perror("tftp: bind");
|
||||
exit(EX_OSERR);
|
||||
}
|
||||
|
||||
if (iscmd && pargc) {
|
||||
/* -c specified; execute command and exit */
|
||||
struct cmd *c;
|
||||
|
@ -375,7 +400,7 @@ static void getmoreargs(const char *partial, const char *mprompt)
|
|||
|
||||
void setpeer(int argc, char *argv[])
|
||||
{
|
||||
struct hostent *host;
|
||||
int err;
|
||||
|
||||
if (argc < 2) {
|
||||
getmoreargs("connect ", "(to) ");
|
||||
|
@ -388,16 +413,34 @@ void setpeer(int argc, char *argv[])
|
|||
return;
|
||||
}
|
||||
|
||||
host = gethostbyname(argv[1]);
|
||||
if (host == 0) {
|
||||
peeraddr.sa.sa_family = ai_fam;
|
||||
err = set_sock_addr(argv[1], &peeraddr, &hostname);
|
||||
if (err) {
|
||||
connected = 0;
|
||||
printf("%s: unknown host\n", argv[1]);
|
||||
return;
|
||||
}
|
||||
peeraddr.sin_family = host->h_addrtype;
|
||||
bcopy(host->h_addr, &peeraddr.sin_addr, host->h_length);
|
||||
hostname = xstrdup(host->h_name);
|
||||
ai_fam = peeraddr.sa.sa_family;
|
||||
if (f == -1) { /* socket not open */
|
||||
ai_fam_sock = ai_fam;
|
||||
} else { /* socket was already open */
|
||||
if (ai_fam_sock != ai_fam) { /* need reopen socken for new family */
|
||||
union sock_addr sa;
|
||||
|
||||
close(f);
|
||||
ai_fam_sock = ai_fam;
|
||||
f = socket(ai_fam_sock, SOCK_DGRAM, 0);
|
||||
if (f < 0) {
|
||||
perror("tftp: socket");
|
||||
exit(EX_OSERR);
|
||||
}
|
||||
bzero((char *)&sa, sizeof (sa));
|
||||
sa.sa.sa_family = ai_fam_sock;
|
||||
if (pick_port_bind(f, &sa, portrange_from, portrange_to)) {
|
||||
perror("tftp: bind");
|
||||
exit(EX_OSERR);
|
||||
}
|
||||
}
|
||||
}
|
||||
port = sp->s_port;
|
||||
if (argc == 3) {
|
||||
struct servent *usp;
|
||||
|
@ -418,9 +461,13 @@ void setpeer(int argc, char *argv[])
|
|||
}
|
||||
|
||||
if (verbose) {
|
||||
char tmp[INET6_ADDRSTRLEN], *tp;
|
||||
tp = (char *)inet_ntop(peeraddr.sa.sa_family, SOCKADDR_P(&peeraddr),
|
||||
tmp, INET6_ADDRSTRLEN);
|
||||
if (!tp)
|
||||
tp = (char *)"???";
|
||||
printf("Connected to %s (%s), port %u\n",
|
||||
hostname, inet_ntoa(peeraddr.sin_addr),
|
||||
(unsigned int)ntohs(port));
|
||||
hostname, tp, (unsigned int)ntohs(port));
|
||||
}
|
||||
connected = 1;
|
||||
}
|
||||
|
@ -484,7 +531,7 @@ static void settftpmode(const struct modes *newmode)
|
|||
void put(int argc, char *argv[])
|
||||
{
|
||||
int fd;
|
||||
int n;
|
||||
int n, err;
|
||||
char *cp, *targ;
|
||||
|
||||
if (argc < 2) {
|
||||
|
@ -499,8 +546,6 @@ void put(int argc, char *argv[])
|
|||
}
|
||||
targ = argv[argc - 1];
|
||||
if (!literal && strchr(argv[argc - 1], ':')) {
|
||||
struct hostent *hp;
|
||||
|
||||
for (n = 1; n < argc - 1; n++)
|
||||
if (strchr(argv[n], ':')) {
|
||||
putusage(argv[0]);
|
||||
|
@ -509,16 +554,14 @@ void put(int argc, char *argv[])
|
|||
cp = argv[argc - 1];
|
||||
targ = strchr(cp, ':');
|
||||
*targ++ = 0;
|
||||
hp = gethostbyname(cp);
|
||||
if (hp == NULL) {
|
||||
fprintf(stderr, "tftp: %s: ", cp);
|
||||
herror((char *)NULL);
|
||||
peeraddr.sa.sa_family = ai_fam;
|
||||
err = set_sock_addr(cp, &peeraddr,&hostname);
|
||||
if (err) {
|
||||
connected = 0;
|
||||
return;
|
||||
}
|
||||
bcopy(hp->h_addr, &peeraddr.sin_addr, hp->h_length);
|
||||
peeraddr.sin_family = hp->h_addrtype;
|
||||
ai_fam = peeraddr.sa.sa_family;
|
||||
connected = 1;
|
||||
hostname = xstrdup(hp->h_name);
|
||||
}
|
||||
if (!connected) {
|
||||
printf("No target machine specified.\n");
|
||||
|
@ -535,7 +578,7 @@ void put(int argc, char *argv[])
|
|||
if (verbose)
|
||||
printf("putting %s to %s:%s [%s]\n",
|
||||
cp, hostname, targ, mode->m_mode);
|
||||
peeraddr.sin_port = port;
|
||||
sa_set_port(&peeraddr, port);
|
||||
tftp_sendfile(fd, targ, mode->m_mode);
|
||||
return;
|
||||
}
|
||||
|
@ -554,7 +597,7 @@ void put(int argc, char *argv[])
|
|||
if (verbose)
|
||||
printf("putting %s to %s:%s [%s]\n",
|
||||
argv[n], hostname, targ, mode->m_mode);
|
||||
peeraddr.sin_port = port;
|
||||
sa_set_port(&peeraddr, port);
|
||||
tftp_sendfile(fd, targ, mode->m_mode);
|
||||
}
|
||||
}
|
||||
|
@ -597,19 +640,15 @@ void get(int argc, char *argv[])
|
|||
if (literal || src == NULL)
|
||||
src = argv[n];
|
||||
else {
|
||||
struct hostent *hp;
|
||||
int err;
|
||||
|
||||
*src++ = 0;
|
||||
hp = gethostbyname(argv[n]);
|
||||
if (hp == NULL) {
|
||||
fprintf(stderr, "tftp: %s: ", argv[n]);
|
||||
herror((char *)NULL);
|
||||
peeraddr.sa.sa_family = ai_fam;
|
||||
err = set_sock_addr(argv[n], &peeraddr, &hostname);
|
||||
if (err)
|
||||
continue;
|
||||
}
|
||||
bcopy(hp->h_addr, (caddr_t) & peeraddr.sin_addr, hp->h_length);
|
||||
peeraddr.sin_family = hp->h_addrtype;
|
||||
ai_fam = peeraddr.sa.sa_family;
|
||||
connected = 1;
|
||||
hostname = xstrdup(hp->h_name);
|
||||
}
|
||||
if (argc < 4) {
|
||||
cp = argc == 3 ? argv[2] : tail(src);
|
||||
|
@ -623,7 +662,7 @@ void get(int argc, char *argv[])
|
|||
if (verbose)
|
||||
printf("getting from %s:%s to %s [%s]\n",
|
||||
hostname, src, cp, mode->m_mode);
|
||||
peeraddr.sin_port = port;
|
||||
sa_set_port(&peeraddr, port);
|
||||
tftp_recvfile(fd, src, mode->m_mode);
|
||||
break;
|
||||
}
|
||||
|
@ -638,7 +677,7 @@ void get(int argc, char *argv[])
|
|||
if (verbose)
|
||||
printf("getting from %s:%s to %s [%s]\n",
|
||||
hostname, src, cp, mode->m_mode);
|
||||
peeraddr.sin_port = port;
|
||||
sa_set_port(&peeraddr, port);
|
||||
tftp_recvfile(fd, src, mode->m_mode);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue