rpms/tftp/F-9 tftp-hpa-0.48-ipv6.patch, NONE, 1.1 tftp.spec, 1.46, 1.47
Jiri Skala
jskala at fedoraproject.org
Fri Nov 21 10:04:50 UTC 2008
- Previous message (by thread): rpms/gyachi/devel .cvsignore, 1.18, 1.19 gyachi.spec, 1.31, 1.32 sources, 1.22, 1.23
- Next message (by thread): rpms/kde-l10n/devel .cvsignore, 1.14, 1.15 kde-l10n.spec, 1.48, 1.49 sources, 1.15, 1.16
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
Author: jskala
Update of /cvs/extras/rpms/tftp/F-9
In directory cvs1.fedora.phx.redhat.com:/tmp/cvs-serv24607
Modified Files:
tftp.spec
Added Files:
tftp-hpa-0.48-ipv6.patch
Log Message:
* Fri Nov 21 2008 Jiri Skala <jskala at redhat.com> - 0.48-7
- #461525 - tftp server and client support IPv6 now
tftp-hpa-0.48-ipv6.patch:
--- NEW FILE tftp-hpa-0.48-ipv6.patch ---
diff -up tftp-hpa-0.48/common/tftpsubs.c.ipv6 tftp-hpa-0.48/common/tftpsubs.c
--- tftp-hpa-0.48/common/tftpsubs.c.ipv6 2007-01-31 00:51:05.000000000 +0100
+++ tftp-hpa-0.48/common/tftpsubs.c 2008-11-21 10:37:18.000000000 +0100
@@ -37,6 +37,7 @@
*/
#include "tftpsubs.h"
+#include "tftpd/tftpd.h"
#ifndef lint
/* static char sccsid[] = "@(#)tftpsubs.c 8.1 (Berkeley) 6/6/93"; */
@@ -249,7 +250,7 @@ synchnet(int f) /* socket to flush */
{
int pktcount = 0;
char rbuf[PKTSIZE];
- struct sockaddr_in from;
+ union sockaddr_uni from;
socklen_t fromlen;
fd_set socketset;
struct timeval notime;
@@ -265,7 +266,7 @@ synchnet(int f) /* socket to flush */
/* Otherwise drain the packet */
pktcount++;
- fromlen = sizeof from;
+ fromlen = SA_ADDRLEN(&from);
(void) recvfrom(f, rbuf, sizeof (rbuf), 0,
(struct sockaddr *)&from, &fromlen);
}
@@ -274,10 +275,11 @@ synchnet(int f) /* socket to flush */
}
-int pick_port_bind(int sockfd, struct sockaddr_in *myaddr, unsigned int port_range_from, unsigned int port_range_to)
+int pick_port_bind(int sockfd, union sockaddr_uni *myaddr, unsigned int port_range_from, unsigned int port_range_to)
{
unsigned int port, firstport;
int port_range = 0;
+ int addrlen;
if (port_range_from != 0 && port_range_to != 0) {
port_range = 1;
@@ -290,9 +292,9 @@ int pick_port_bind(int sockfd, struct so
port = firstport;
do {
- myaddr->sin_port = htons(port);
-
- if (bind(sockfd, (struct sockaddr *)myaddr, sizeof *myaddr) < 0) {
+ SA_PORT(myaddr) = htons(port);
+ addrlen = IS_IPv6(myaddr) ? sizeof(myaddr->s_in6) : sizeof(myaddr->s_in);
+ if (bind(sockfd, (struct sockaddr *)myaddr, addrlen) < 0) {
/* Some versions of Linux return EINVAL instead of EADDRINUSE */
if ( !(port_range && (errno == EINVAL || errno == EADDRINUSE)) )
return -1;
diff -up tftp-hpa-0.48/common/tftpsubs.h.ipv6 tftp-hpa-0.48/common/tftpsubs.h
--- tftp-hpa-0.48/common/tftpsubs.h.ipv6 2007-01-31 00:51:05.000000000 +0100
+++ tftp-hpa-0.48/common/tftpsubs.h 2008-11-21 10:37:18.000000000 +0100
@@ -46,6 +46,7 @@
#define TFTPSUBS_H
#include "config.h"
+#include "tftpd/tftpd.h"
struct tftphdr;
@@ -62,6 +63,6 @@ int writeit(FILE *, struct tftphdr **, i
extern int segsize;
#define MAX_SEGSIZE 65464
-int pick_port_bind(int sockfd, struct sockaddr_in *myaddr, unsigned int from, unsigned int to);
+int pick_port_bind(int sockfd, union sockaddr_uni *myaddr, unsigned int from, unsigned int to);
#endif
diff -up tftp-hpa-0.48/tftpd/recvfrom.c.ipv6 tftp-hpa-0.48/tftpd/recvfrom.c
--- tftp-hpa-0.48/tftpd/recvfrom.c.ipv6 2007-01-31 00:51:05.000000000 +0100
+++ tftp-hpa-0.48/tftpd/recvfrom.c 2008-11-21 10:37:18.000000000 +0100
@@ -34,8 +34,10 @@
/* Assume this version of glibc simply lacks the definition */
struct in_pktinfo {
int ipi_ifindex;
- struct in_addr ipi_spec_dst;
- struct in_addr ipi_addr;
+ union {
+ struct in_addr sin_addr;
+ struct in6_addr sin6_addr;
+ } ipi_spec_dst, ipi_addr;
};
# else
# undef IP_PKTINFO /* No definition, no way to get it */
@@ -55,30 +57,38 @@ struct in_pktinfo {
* end up having the same local and remote address when trying to
* bind to it.
*/
-static int address_is_local(const struct sockaddr_in *addr)
+static int address_is_local(const union sockaddr_uni *addr)
{
- struct sockaddr_in sin;
+ union sockaddr_uni sin;
int sockfd = -1;
int e;
int rv = 0;
socklen_t addrlen;
/* Multicast or universal broadcast address? */
- if (ntohl(addr->sin_addr.s_addr) >= (224UL << 24))
- return 0;
+ if (ipv6) {
+ if (addr->s_in6.sin6_addr.s6_addr[0] == 255)
+ return 0;
+ } else {
+ if (ntohl(addr->s_in.sin_addr.s_addr) >= (224UL << 24))
+ return 0;
+ }
- sockfd = socket(PF_INET, SOCK_DGRAM, 0);
+ sockfd = socket(SA_FAMILY(addr), SOCK_DGRAM, 0);
if (sockfd < 0)
goto err;
- if (connect(sockfd, (const struct sockaddr *)addr, sizeof *addr))
+ addrlen = ipv6 ? sizeof(sin.s_in6) : sizeof(sin.s_in);
+ if (connect(sockfd, (const struct sockaddr *)addr, addrlen))
goto err;
- addrlen = sizeof sin;
+ addrlen = ipv6 ? sizeof(sin.s_in6) : sizeof(sin.s_in);
if (getsockname(sockfd, (struct sockaddr *)&sin, &addrlen))
goto err;
- rv = sin.sin_addr.s_addr == addr->sin_addr.s_addr;
+ if (ipv6)
+ rv = !memcmp(&sin.s_in6.sin6_addr, &addr->s_in6.sin6_addr, sizeof(struct in6_addr));
+ else rv = sin.s_in.sin_addr.s_addr == addr->s_in.sin_addr.s_addr;
err:
e = errno;
@@ -93,8 +103,8 @@ static int address_is_local(const struct
int
myrecvfrom(int s, void *buf, int len, unsigned int flags,
- struct sockaddr *from, socklen_t *fromlen,
- struct sockaddr_in *myaddr)
+ union sockaddr_uni *from, socklen_t *fromlen,
+ union sockaddr_uni *myaddr)
{
struct msghdr msg;
struct iovec iov;
@@ -103,10 +113,10 @@ myrecvfrom(int s, void *buf, int len, un
union {
struct cmsghdr cm;
#ifdef IP_PKTINFO
- char control[CMSG_SPACE(sizeof(struct in_addr)) +
+ char control[CMSG_SPACE(sizeof(struct in6_addr)) +
CMSG_SPACE(sizeof(struct in_pktinfo))];
#else
- char control[CMSG_SPACE(sizeof(struct in_addr))];
+ char control[CMSG_SPACE(sizeof(struct in6_addr))];
#endif
} control_un;
int on = 1;
@@ -140,8 +150,8 @@ myrecvfrom(int s, void *buf, int len, un
*fromlen = msg.msg_namelen;
if ( myaddr ) {
- bzero(myaddr, sizeof(struct sockaddr_in));
- myaddr->sin_family = AF_INET;
+ bzero(myaddr, sizeof(union sockaddr_uni));
+ SA_FAMILY(myaddr) = ipv6 ? AF_INET6 : AF_INET;
if ( msg.msg_controllen < sizeof(struct cmsghdr) ||
(msg.msg_flags & MSG_CTRUNC) )
@@ -151,27 +161,34 @@ myrecvfrom(int s, void *buf, int len, un
cmptr = CMSG_NXTHDR(&msg, cmptr) ) {
#ifdef IP_RECVDSTADDR
- if ( cmptr->cmsg_level == IPPROTO_IP &&
- cmptr->cmsg_type == IP_RECVDSTADDR ) {
- memcpy(&myaddr->sin_addr, CMSG_DATA(cmptr),
- sizeof(struct in_addr));
- }
+ if ( cmptr->cmsg_level == IPPROTO_IP &&
+ cmptr->cmsg_type == IP_RECVDSTADDR ) {
+ if (IS_IPv6(*myaddr)))
+ memcpy(&myaddr->s_sin6.sin6_addr, CMSG_DATA(cmptr), sizeof(struct in6_addr));
+ else memcpy(&myaddr->s_sin.sin_addr, CMSG_DATA(cmptr), sizeof(struct in_addr));
+ }
#endif
#ifdef IP_PKTINFO
- if ( cmptr->cmsg_level == IPPROTO_IP &&
- cmptr->cmsg_type == IP_PKTINFO ) {
- memcpy(&pktinfo, CMSG_DATA(cmptr), sizeof(struct in_pktinfo));
- memcpy(&myaddr->sin_addr, &pktinfo.ipi_addr, sizeof(struct in_addr));
- }
+ if ( cmptr->cmsg_level == IPPROTO_IP &&
+ cmptr->cmsg_type == IP_PKTINFO ) {
+ memcpy(&pktinfo, CMSG_DATA(cmptr), sizeof(struct in_pktinfo));
+ if (ipv6)
+ memcpy(&myaddr->s_in6.sin6_addr, &pktinfo.ipi_addr, sizeof(struct in6_addr));
+ else memcpy(&myaddr->s_in.sin_addr, &pktinfo.ipi_addr, sizeof(struct in_addr));
+ }
#endif
}
}
/* If the address is not a valid local address, then bind to any address... */
- if (address_is_local(myaddr) != 1)
- myaddr->sin_addr.s_addr = INADDR_ANY;
+ if (address_is_local(myaddr) != 1) {
+ if (SA_FAMILY(myaddr) == AF_INET6)
+ memcpy(&myaddr->s_in6.sin6_addr, &in6addr_any, sizeof (struct in6_addr));
+ else myaddr->s_in.sin_addr.s_addr = INADDR_ANY;
+
+ }
return n;
}
@@ -180,16 +197,17 @@ myrecvfrom(int s, void *buf, int len, un
int
myrecvfrom(int s, void *buf, int len, unsigned int flags,
- struct sockaddr *from, int *fromlen,
- struct sockaddr_in *myaddr)
+ union sockaddr_uni *from, int *fromlen,
+ union sockaddr_uni *myaddr)
{
/* There is no way we can get the local address, fudge it */
+ bzero(myaddr, sizeof(union sockaddr_uni));
+ SA_FAMILY(myaddr) = ipv6 ? AF_INET6 : AF_INET;
- bzero(myaddr, sizeof(struct sockaddr_in));
- myaddr->sin_family = AF_INET;
-
- myaddr->sin_port = htons(IPPORT_TFTP);
- bzero(&myaddr->sin_addr, sizeof(myaddr->sin_addr));
+ SA_PORT(myaddr) = htons(IPPORT_TFTP);
+ if (SA_FAMILY(myaddr) == AF_INET6)
+ bzero(&myaddr->s_in6.sin6_addr, sizeof(struct in6_addr));
+ else myaddr->s_in.s_sin_addr.s_addr = 0L;
return recvfrom(s,buf,len,flags,from,fromlen);
}
diff -up tftp-hpa-0.48/tftpd/recvfrom.h.ipv6 tftp-hpa-0.48/tftpd/recvfrom.h
--- tftp-hpa-0.48/tftpd/recvfrom.h.ipv6 2007-01-31 00:51:05.000000000 +0100
+++ tftp-hpa-0.48/tftpd/recvfrom.h 2008-11-21 10:37:18.000000000 +0100
@@ -16,8 +16,9 @@
*/
#include "config.h"
+#include "tftpd.h"
int
myrecvfrom(int s, void *buf, int len, unsigned int flags,
- struct sockaddr *from, socklen_t *fromlen,
- struct sockaddr_in *myaddr);
+ union sockaddr_uni *from, socklen_t *fromlen,
+ union sockaddr_uni *myaddr);
diff -up tftp-hpa-0.48/tftpd/tftpd.8.in.ipv6 tftp-hpa-0.48/tftpd/tftpd.8.in
--- tftp-hpa-0.48/tftpd/tftpd.8.in.ipv6 2007-01-31 00:51:05.000000000 +0100
+++ tftp-hpa-0.48/tftpd/tftpd.8.in 2008-11-21 10:37:18.000000000 +0100
@@ -173,6 +173,12 @@ specified range of port numbers.
.B \-V
Print the version number and configuration to standard output, then
exit gracefully.
+.TP
+.B \-4
+support IPv4 only (by default)
+.TP
+.B \-6
+prefer IPv6
.SH "RFC 2347 OPTION NEGOTIATION"
This version of
.B tftpd
diff -up tftp-hpa-0.48/tftpd/tftpd.c.ipv6 tftp-hpa-0.48/tftpd/tftpd.c
--- tftp-hpa-0.48/tftpd/tftpd.c.ipv6 2008-11-21 10:37:18.000000000 +0100
+++ tftp-hpa-0.48/tftpd/tftpd.c 2008-11-21 10:37:18.000000000 +0100
@@ -94,7 +94,7 @@ char buf[PKTSIZE];
char ackbuf[PKTSIZE];
unsigned int max_blksize = MAX_SEGSIZE;
-struct sockaddr_in from;
+union sockaddr_uni from;
socklen_t fromlen;
off_t tsize;
int tsize_ok;
@@ -108,6 +108,7 @@ int unixperms = 0;
int portrange = 0;
unsigned int portrange_from, portrange_to;
int verbosity = 0;
+int ipv6 = 0;
struct formats;
#ifdef WITH_REGEX
@@ -161,7 +162,7 @@ timer(int sig)
static void
usage(void)
{
- syslog(LOG_ERR, "Usage: %s [-vcl][-a address][-m mappings][-u user][-t inetd_timeout][-T pkt_timeout][-r option...] [-s] [directory ...]",
+ syslog(LOG_ERR, "Usage: %s [-vcl46][-a address][-m mappings][-u user][-t inetd_timeout][-T pkt_timeout][-r option...] [-s] [directory ...]",
__progname);
exit(EX_USAGE);
}
@@ -278,8 +279,8 @@ main(int argc, char **argv)
struct tftphdr *tp;
struct passwd *pw;
struct options *opt;
- struct sockaddr_in myaddr;
- struct sockaddr_in bindaddr;
+ union sockaddr_uni myaddr;
+ union sockaddr_uni bindaddr;
int n;
int fd = 0;
int standalone = 0; /* Standalone (listen) mode */
@@ -300,6 +301,7 @@ main(int argc, char **argv)
time_t my_time = 0;
struct tm* p_tm;
char envtz[10];
+ char dbuf[INET6_ADDRSTRLEN];
my_time = time(NULL);
p_tm = localtime(&my_time);
snprintf(envtz, sizeof(envtz) - 1, "UTC%+d", (p_tm->tm_gmtoff * -1)/3600);
@@ -314,7 +316,7 @@ main(int argc, char **argv)
srand(time(NULL) ^ getpid());
- while ((c = getopt(argc, argv, "cspvVlLa:B:u:U:r:t:T:R:m:")) != -1)
+ while ((c = getopt(argc, argv, "cspvVlL46a:B:u:U:r:t:T:R:m:")) != -1)
switch (c) {
case 'c':
cancreate = 1;
@@ -338,6 +340,12 @@ main(int argc, char **argv)
case 't':
waittime = atoi(optarg);
break;
+ case '4':
+ ipv6 = 0;
+ break;
+ case '6':
+ ipv6 = 1;
+ break;
case 'B':
{
char *vp;
@@ -459,31 +467,46 @@ main(int argc, char **argv)
/* If we're running standalone, set up the input port */
if ( standalone ) {
- fd = socket(PF_INET, SOCK_DGRAM, 0);
+ fd = socket(ipv6 ? AF_INET6 : AF_INET, SOCK_DGRAM, 0);
- memset(&bindaddr, 0, sizeof bindaddr);
- bindaddr.sin_family = AF_INET;
- bindaddr.sin_addr.s_addr = INADDR_ANY;
- bindaddr.sin_port = htons(IPPORT_TFTP);
+ bzero(&bindaddr, sizeof bindaddr);
+ SA_FAMILY(&bindaddr) = ipv6 ? AF_INET6 : AF_INET;
+ SA_PORT(&bindaddr) = htons(IPPORT_TFTP);
+ if (IS_IPv4(&bindaddr))
+ bindaddr.s_in.sin_addr.s_addr = INADDR_ANY;
+ else bindaddr.s_in6.sin6_addr = in6addr_any;
if ( address ) {
char *portptr, *eportptr;
- struct hostent *hostent;
+ struct addrinfo hints, *res;
+ int error;
struct servent *servent;
unsigned long port;
- address = tfstrdup(address);
- portptr = strrchr(address, ':');
- if ( portptr )
- *portptr++ = '\0';
+ address = tfstrdup(address);
+ portptr = strrchr(address, ':');
+ if ( portptr )
+ *portptr++ = '\0';
if ( *address ) {
- hostent = gethostbyname(address);
- if ( !hostent || hostent->h_addrtype != AF_INET ) {
- syslog(LOG_ERR, "cannot resolve local bind address: %s", address);
- exit(EX_NOINPUT);
- }
- memcpy(&bindaddr.sin_addr, hostent->h_addr, hostent->h_length);
+ memset(&hints, 0, sizeof (struct addrinfo));
+ hints.ai_family = SA_FAMILY(&bindaddr);
+ hints.ai_flags = AI_CANONNAME;
+ hints.ai_socktype = SOCK_DGRAM;
+
+ error = getaddrinfo(address, portptr, &hints, &res);
+ if (error != 0) {
+ syslog(LOG_ERR, "%s unknown host", address);
+ exit(EX_NOHOST);
+ }
+
+ for (; res; res = res->ai_next) {
+ fd = socket(SA_FAMILY(res), res->ai_socktype, 0);
+ if (fd > -1) {
+ memcpy(&bindaddr, res->ai_addr, res->ai_addrlen);
+ break;
+ }
+ }
} else {
/* Default to using INADDR_ANY */
}
@@ -491,9 +514,9 @@ main(int argc, char **argv)
if ( portptr && *portptr ) {
servent = getservbyname(portptr, "udp");
if ( servent ) {
- bindaddr.sin_port = servent->s_port;
+ SA_PORT(&bindaddr) = servent->s_port;
} else if ( (port = strtoul(portptr, &eportptr, 0)) && !*eportptr ) {
- bindaddr.sin_port = htons(port);
+ SA_PORT(&bindaddr) = htons(port);
} else if ( !strcmp(portptr, "tftp") ) {
/* It's TFTP, we're OK */
} else {
@@ -595,15 +618,20 @@ main(int argc, char **argv)
}
}
- if ( from.sin_family != AF_INET ) {
+ if ( SA_FAMILY(&from) != AF_INET && SA_FAMILY(&from) != AF_INET6 ) {
syslog(LOG_ERR, "received address was not AF_INET, please check your inetd config");
exit(EX_PROTOCOL);
}
- if ( standalone && myaddr.sin_addr.s_addr == INADDR_ANY ) {
+ if (standalone && IS_IPv4(&myaddr) &&
+ myaddr.s_in.sin_addr.s_addr == INADDR_ANY ) {
/* myrecvfrom() didn't capture the source address; but we might
have bound to a specific address, if so we should use it */
- memcpy(&myaddr.sin_addr, &bindaddr.sin_addr, sizeof bindaddr.sin_addr);
+ memcpy(&myaddr.s_in.sin_addr, &bindaddr.s_in.sin_addr, sizeof bindaddr.s_in.sin_addr);
+ }
+ if (standalone && IS_IPv6(&myaddr) &&
+ !memcmp(&myaddr.s_in6.sin6_addr, &in6addr_any, sizeof(struct in6_addr)) ) {
+ memcpy(&myaddr.s_in6.sin6_addr, &bindaddr.s_in6.sin6_addr, sizeof bindaddr.s_in6.sin6_addr);
}
/*
@@ -636,11 +664,11 @@ main(int argc, char **argv)
if ( hosts_access(&wrap_request) == 0 ) {
if ( deny_severity != -1 )
syslog(deny_severity, "connection refused from %s",
- inet_ntoa(from.sin_addr));
+ inet_ntop(SA_FAMILY(&from), pSA_ADDR(&from), dbuf, INET6_ADDRSTRLEN));
exit(EX_NOPERM); /* Access denied */
} else if ( allow_severity != -1 ) {
syslog(allow_severity, "connect from %s",
- inet_ntoa(from.sin_addr));
+ inet_ntop(SA_FAMILY(&from), pSA_ADDR(&from), dbuf, INET6_ADDRSTRLEN));
}
#endif
@@ -650,7 +678,7 @@ main(int argc, char **argv)
/* Get a socket. This has to be done before the chroot(), since
some systems require access to /dev to create a socket. */
- peer = socket(AF_INET, SOCK_DGRAM, 0);
+ peer = socket(ipv6 ? AF_INET6 : AF_INET, SOCK_DGRAM, 0);
if (peer < 0) {
syslog(LOG_ERR, "socket: %m");
exit(EX_IOERR);
@@ -703,7 +731,7 @@ main(int argc, char **argv)
}
/* Other basic setup */
- from.sin_family = AF_INET;
+ SA_FAMILY(&from) = ipv6 ? AF_INET6 : AF_INET;
/* Process the request... */
if (pick_port_bind(peer, &myaddr, portrange_from, portrange_to) < 0) {
@@ -760,6 +788,7 @@ tftp(struct tftphdr *tp, int size)
char *val = NULL, *opt = NULL;
char *ap = ackbuf + 2;
+ char dbuf[INET6_ADDRSTRLEN];
((struct tftphdr *)ackbuf)->th_opcode = htons(OACK);
@@ -801,11 +830,11 @@ tftp(struct tftphdr *tp, int size)
if ( filename == origfilename || !strcmp(filename, origfilename) )
syslog(LOG_NOTICE, "%s from %s filename %s\n",
tp_opcode == WRQ ? "WRQ" : "RRQ",
- inet_ntoa(from.sin_addr), filename);
+ inet_ntop(SA_FAMILY(&from), pSA_ADDR(&from), dbuf, INET6_ADDRSTRLEN), filename);
else
syslog(LOG_NOTICE, "%s from %s filename %s remapped to %s\n",
tp_opcode == WRQ ? "WRQ" : "RRQ",
- inet_ntoa(from.sin_addr), origfilename, filename);
+ inet_ntop(SA_FAMILY(&from), pSA_ADDR(&from), dbuf, INET6_ADDRSTRLEN), origfilename, filename);
}
ecode = (*pf->f_validate)(filename, tp_opcode, pf, &errmsgptr);
if (ecode) {
@@ -1024,18 +1053,23 @@ int
rewrite_macros(char macro, char *output)
{
char *p;
+ int i;
+ char dbuf[INET6_ADDRSTRLEN];
switch (macro) {
case 'i':
- p = inet_ntoa(from.sin_addr);
+ p = inet_ntop(SA_FAMILY(&from), pSA_ADDR(&from), dbuf, INET6_ADDRSTRLEN);
if ( output )
strcpy(output, p);
return strlen(p);
case 'x':
- if ( output )
- sprintf(output, "%08lX", (unsigned long)ntohl(from.sin_addr.s_addr));
- return 8;
+ if ( output && ipv6 ) {
+ for (i=0; i < sizeof (from.s_in6.sin6_addr.s6_addr); i++)
+ sprintf(output+2*i, "%02x", from.s_in6.sin6_addr.s6_addr[i]);
+ } else if ( output )
+ sprintf(output, "%08lX", (unsigned long)ntohl(from.s_in.sin_addr.s_addr));
+ return ipv6 ? 32 : 8;
default:
return -1;
@@ -1403,6 +1437,7 @@ nak(int error, const char *msg)
{
struct tftphdr *tp;
int length;
+ char dbuf[INET6_ADDRSTRLEN];
tp = (struct tftphdr *)buf;
tp->th_opcode = htons((u_short)ERROR);
@@ -1428,7 +1463,7 @@ nak(int error, const char *msg)
if ( verbosity >= 2 ) {
syslog(LOG_INFO, "sending NAK (%d, %s) to %s",
- error, tp->th_msg, inet_ntoa(from.sin_addr));
+ error, tp->th_msg, inet_ntop(SA_FAMILY(&from), pSA_ADDR(&from), dbuf, INET6_ADDRSTRLEN));
}
if (send(peer, buf, length, 0) != length)
diff -up tftp-hpa-0.48/tftpd/tftpd.h.ipv6 tftp-hpa-0.48/tftpd/tftpd.h
--- tftp-hpa-0.48/tftpd/tftpd.h.ipv6 2007-01-31 00:51:05.000000000 +0100
+++ tftp-hpa-0.48/tftpd/tftpd.h 2008-11-21 10:37:18.000000000 +0100
@@ -18,10 +18,32 @@
#ifndef TFTPD_TFTPD_H
#define TFTPD_TFTPD_H
+#include <netinet/in.h>
+
+union sockaddr_uni
+{
+ struct {
+ sa_family_t si_family;
+ in_port_t si_port;
+ } s_si;
+ struct sockaddr s_sa;
+ struct sockaddr_in s_in;
+ struct sockaddr_in6 s_in6;
+};
+
+#define SCK(p) ((union sockaddr_uni *)p)
+#define IS_IPv4(p) (SCK(p)->s_si.si_family == AF_INET)
+#define IS_IPv6(p) (SCK(p)->s_si.si_family == AF_INET6)
+#define SA_FAMILY(p) SCK(p)->s_si.si_family
+#define SA_PORT(p) SCK(p)->s_si.si_port
+#define pSA_ADDR(p) ((void *)(IS_IPv4(p) ? &(SCK(p)->s_in.sin_addr) : &(SCK(p)->s_in6.sin6_addr)))
+#define SA_ADDRLEN(p) (IS_IPv4(p) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6))
+
void set_signal(int, void (*)(int), int);
void *tfmalloc(size_t);
char *tfstrdup(const char *);
extern int verbosity;
+extern int ipv6;
#endif
diff -up tftp-hpa-0.48/tftp/main.c.ipv6 tftp-hpa-0.48/tftp/main.c
--- tftp-hpa-0.48/tftp/main.c.ipv6 2007-01-31 00:51:05.000000000 +0100
+++ tftp-hpa-0.48/tftp/main.c 2008-11-21 10:37:18.000000000 +0100
@@ -35,6 +35,7 @@
*/
#include "common/tftpsubs.h"
+#include "tftpd/tftpd.h"
#ifndef lint
static const char *copyright UNUSED =
@@ -84,7 +85,7 @@ static const struct modes modes[] = {
#define MODE_NETASCII (&modes[0])
#define MODE_DEFAULT MODE_NETASCII
-struct sockaddr_in peeraddr;
+union sockaddr_uni peeraddr;
int f;
u_short port;
int trace;
@@ -202,7 +203,6 @@ static inline void usage(int errcode)
int
main(int argc, char *argv[])
{
- struct sockaddr_in s_in;
int arg;
static int pargc, peerargc;
static int iscmd = 0;
@@ -290,17 +290,6 @@ main(int argc, char *argv[])
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 ) {
@@ -380,10 +369,50 @@ getmoreargs(const char *partial, const c
#endif
}
+int
+getinfo(char *host)
+{
+ struct addrinfo hints, *res;
+ int error, ret = 0;
+ char pbuf[NI_MAXSERV];
+
+ sprintf(pbuf, "%d", ntohs(sp->s_port));
+ memset(&hints, 0, sizeof (struct addrinfo));
+ hints.ai_flags = AI_CANONNAME;
+ hints.ai_socktype = SOCK_DGRAM;
+
+ error = getaddrinfo(host, pbuf, &hints, &res);
+ if (error != 0) {
+ printf("%s: unknown host\n", host);
+ return ret;
+ }
+
+ for (; res; res = res->ai_next) {
+ f = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
+
+ if (f > -1) {
+ ret = 1;
+ bzero(&peeraddr, sizeof (union sockaddr_uni));
+ if (res->ai_family == AF_INET)
+ bcopy(res->ai_addr, &peeraddr.s_in, res->ai_addrlen);
+ else if (res->ai_family == AF_INET6)
+ bcopy(res->ai_addr, &peeraddr.s_in6, res->ai_addrlen);
+ else ret = 0;
+
+ if (ret)
+ hostname = xstrdup(res->ai_canonname ? res->ai_canonname : host);
+ break;
+ }
+ }
+ freeaddrinfo(res);
+ return ret;
+}
+
void
setpeer(int argc, char *argv[])
{
- struct hostent *host;
+ static union sockaddr_uni s_inx;
+ char dbuf[INET6_ADDRSTRLEN];
if (argc < 2) {
getmoreargs("connect ", "(to) ");
@@ -396,15 +425,20 @@ setpeer(int argc, char *argv[])
return;
}
- host = gethostbyname(argv[1]);
- if (host == 0) {
- connected = 0;
- printf("%s: unknown host\n", argv[1]);
- return;
+ connected = getinfo(argv[1]);
+
+ // TODO correct this
+ if (f < 0) {
+ perror("tftp: socket");
+ exit(EX_OSERR);
+ }
+
+ bzero(&s_inx, sizeof (union sockaddr_uni));
+ SA_FAMILY(&s_inx) = SA_FAMILY(&peeraddr);
+ if (pick_port_bind(f, &s_inx, portrange_from, portrange_to)) {
+ perror("tftp: bind");
+ exit(EX_OSERR);
}
- peeraddr.sin_family = host->h_addrtype;
- bcopy(host->h_addr, &peeraddr.sin_addr, host->h_length);
- hostname = xstrdup(host->h_name);
port = sp->s_port;
if (argc == 3) {
@@ -427,8 +461,9 @@ setpeer(int argc, char *argv[])
if (verbose) {
printf("Connected to %s (%s), port %u\n",
- hostname, inet_ntoa(peeraddr.sin_addr),
- (unsigned int)ntohs(port));
+ hostname,
+ inet_ntop(SA_FAMILY(&peeraddr), pSA_ADDR(&peeraddr), dbuf, INET6_ADDRSTRLEN),
+ (unsigned int)ntohs(port));
}
connected = 1;
}
@@ -521,16 +556,7 @@ 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);
- return;
- }
- bcopy(hp->h_addr, &peeraddr.sin_addr, hp->h_length);
- peeraddr.sin_family = hp->h_addrtype;
- connected = 1;
- hostname = xstrdup(hp->h_name);
+ connected = getinfo(cp);
}
if (!connected) {
printf("No target machine specified.\n");
@@ -546,7 +572,7 @@ 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_PORT(&peeraddr) = port;
tftp_sendfile(fd, targ, mode->m_mode);
return;
}
@@ -564,7 +590,7 @@ 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_PORT(&peeraddr) = port;
tftp_sendfile(fd, targ, mode->m_mode);
}
}
@@ -612,17 +638,7 @@ get(int argc, char *argv[])
struct hostent *hp;
*src++ = 0;
- hp = gethostbyname(argv[n]);
- if (hp == NULL) {
- fprintf(stderr, "tftp: %s: ", argv[n]);
- herror((char *)NULL);
- continue;
- }
- bcopy(hp->h_addr, (caddr_t)&peeraddr.sin_addr,
- hp->h_length);
- peeraddr.sin_family = hp->h_addrtype;
- connected = 1;
- hostname = xstrdup(hp->h_name);
+ connected = getinfo(argv[n]);
}
if (argc < 4) {
cp = argc == 3 ? argv[2] : tail(src);
@@ -634,7 +650,7 @@ 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_PORT(&peeraddr) = port;
tftp_recvfile(fd, src, mode->m_mode);
break;
}
@@ -647,7 +663,7 @@ 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_PORT(&peeraddr) = port;
tftp_recvfile(fd, src, mode->m_mode);
}
}
diff -up tftp-hpa-0.48/tftp/tftp.c.ipv6 tftp-hpa-0.48/tftp/tftp.c
--- tftp-hpa-0.48/tftp/tftp.c.ipv6 2007-01-31 00:51:05.000000000 +0100
+++ tftp-hpa-0.48/tftp/tftp.c 2008-11-21 10:37:18.000000000 +0100
@@ -35,6 +35,7 @@
*/
#include "common/tftpsubs.h"
+#include "tftpd/tftpd.h"
#ifndef lint
/* static char sccsid[] = "@(#)tftp.c 8.1 (Berkeley) 6/6/93"; */
@@ -50,7 +51,7 @@ static const char *rcsid UNUSED =
*/
#include "extern.h"
-extern struct sockaddr_in peeraddr; /* filled in by main */
+extern union sockaddr_uni peeraddr; /* filled in by main */
extern int f; /* the opened socket */
extern int trace;
extern int verbose;
@@ -84,7 +85,7 @@ tftp_sendfile(int fd, const char *name,
volatile u_short block;
volatile int size, convert;
volatile off_t amount;
- struct sockaddr_in from;
+ union sockaddr_uni from;
socklen_t fromlen;
FILE *file;
u_short ap_opcode, ap_block;
@@ -118,16 +119,19 @@ tftp_sendfile(int fd, const char *name,
if (trace)
tpacket("sent", dp, size + 4);
n = sendto(f, dp, size + 4, 0,
- (struct sockaddr *)&peeraddr, sizeof(peeraddr));
+ (struct sockaddr *)&peeraddr, SA_ADDRLEN(&peeraddr));
+
if (n != size + 4) {
perror("tftp: sendto");
goto abort;
}
+
read_ahead(file, convert);
for ( ; ; ) {
alarm(rexmtval);
do {
- fromlen = sizeof(from);
+ from.s_si.si_family = peeraddr.s_si.si_family;
+ fromlen = SA_ADDRLEN(&from);
n = recvfrom(f, ackbuf, sizeof(ackbuf), 0,
(struct sockaddr *)&from, &fromlen);
} while (n <= 0);
@@ -136,7 +140,9 @@ tftp_sendfile(int fd, const char *name,
perror("tftp: recvfrom");
goto abort;
}
- peeraddr.sin_port = from.sin_port; /* added */
+
+ SA_PORT(&peeraddr) = SA_PORT(&from);/* added */
+
if (trace)
tpacket("received", ap, n);
/* should verify packet came from server */
@@ -192,7 +198,7 @@ tftp_recvfile(int fd, const char *name,
volatile u_short block;
volatile int size, firsttrip;
volatile unsigned long amount;
- struct sockaddr_in from;
+ union sockaddr_uni from;
socklen_t fromlen;
FILE *file;
volatile int convert; /* true if converting crlf -> lf */
@@ -224,7 +230,7 @@ send_ack:
if (trace)
tpacket("sent", ap, size);
if (sendto(f, ackbuf, size, 0, (struct sockaddr *)&peeraddr,
- sizeof(peeraddr)) != size) {
+ SA_ADDRLEN(&peeraddr)) != size) {
alarm(0);
perror("tftp: sendto");
goto abort;
@@ -233,7 +239,8 @@ send_ack:
for ( ; ; ) {
alarm(rexmtval);
do {
- fromlen = sizeof(from);
+ SA_FAMILY(&from) = SA_FAMILY(&peeraddr);
+ fromlen = SA_ADDRLEN(&from);
n = recvfrom(f, dp, PKTSIZE, 0,
(struct sockaddr *)&from, &fromlen);
} while (n <= 0);
@@ -242,7 +249,9 @@ send_ack:
perror("tftp: recvfrom");
goto abort;
}
- peeraddr.sin_port = from.sin_port; /* added */
+
+ SA_PORT(&peeraddr) = SA_PORT(&from);/* added */
+
if (trace)
tpacket("received", dp, n);
/* should verify client address */
@@ -282,7 +291,7 @@ abort: /* ok to ack, since user */
ap->th_opcode = htons((u_short)ACK); /* has seen err msg */
ap->th_block = htons((u_short)block);
(void) sendto(f, ackbuf, 4, 0, (struct sockaddr *)&peeraddr,
- sizeof(peeraddr));
+ SA_ADDRLEN(&peeraddr));
write_behind(file, convert); /* flush last buffer */
fclose(file);
stopclock();
@@ -290,7 +299,6 @@ abort: /* ok to ack, since user */
printstats("Received", amount);
}
-static int
makerequest(int request, const char *name,
struct tftphdr *tp, const char *mode)
{
@@ -359,7 +367,7 @@ nak(int error, const char *msg)
if (trace)
tpacket("sent", tp, length);
if (sendto(f, ackbuf, length, 0, (struct sockaddr *)&peeraddr,
- sizeof(peeraddr)) != length)
+ SA_ADDRLEN(&peeraddr)) != length)
perror("nak");
}
diff -up tftp-hpa-0.48/tftp-xinetd.ipv6 tftp-hpa-0.48/tftp-xinetd
--- tftp-hpa-0.48/tftp-xinetd.ipv6 2008-11-21 10:37:18.000000000 +0100
+++ tftp-hpa-0.48/tftp-xinetd 2008-11-21 10:40:30.000000000 +0100
@@ -3,6 +3,11 @@
# protocol. The tftp protocol is often used to boot diskless \
# workstations, download configuration files to network-aware printers, \
# and to start the installation process for some operating systems.
+#
+# IPv6 support
+# server = -6 -s /var/lib/tftpboot
+# flags = IPv6
+#
service tftp
{
socket_type = dgram
Index: tftp.spec
===================================================================
RCS file: /cvs/extras/rpms/tftp/F-9/tftp.spec,v
retrieving revision 1.46
retrieving revision 1.47
diff -u -r1.46 -r1.47
--- tftp.spec 21 May 2008 21:35:39 -0000 1.46
+++ tftp.spec 21 Nov 2008 10:04:18 -0000 1.47
@@ -3,7 +3,7 @@
Summary: The client for the Trivial File Transfer Protocol (TFTP)
Name: tftp
Version: %{tftp_hpa_version}
-Release: 6%{?dist}
+Release: 7%{?dist}
License: BSD
Group: Applications/Internet
Source0: http://www.kernel.org/pub/software/network/tftp/tftp-hpa-%{tftp_hpa_version}.tar.gz
@@ -12,6 +12,7 @@
Patch0: tftp-0.40-remap.patch
Patch2: tftp-hpa-0.39-tzfix.patch
Patch3: tftp-0.42-tftpboot.patch
+Patch4: tftp-hpa-0.48-ipv6.patch
BuildRequires: tcp_wrappers-devel readline-devel
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
@@ -43,6 +44,7 @@
%patch0 -p1 -b .zero
%patch2 -p1 -b .tzfix
%patch3 -p1 -b .tftpboot
+%patch4 -p1 -b .ipv6
%build
@@ -88,6 +90,9 @@
%{_mandir}/man8/*
%changelog
+* Fri Nov 21 2008 Jiri Skala <jskala at redhat.com> - 0.48-7
+- #461525 - tftp server and client support IPv6 now
+
* Wed May 21 2008 Warren Togami <wtogami at redhat.com. - 0.48-6
- undo symlink stuff completely because they are problematic
See Bug #447135 for details.
- Previous message (by thread): rpms/gyachi/devel .cvsignore, 1.18, 1.19 gyachi.spec, 1.31, 1.32 sources, 1.22, 1.23
- Next message (by thread): rpms/kde-l10n/devel .cvsignore, 1.14, 1.15 kde-l10n.spec, 1.48, 1.49 sources, 1.15, 1.16
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
More information about the fedora-extras-commits
mailing list