mirror of
https://kernel.googlesource.com/pub/scm/network/tftp/tftp-hpa
synced 2025-04-26 01:49:52 +03:00
IPv6 infrastructure support
Add autoconf rules to detect IPv6 availability and some of the neeeded support functions. Add stubs for getaddrinfo and inet_ntop. You can disable IPv6 at compile time with ./configure --without-ipv6 Signed-off-by: Karsten Keil <kkeil@suse.de> Signed-off-by: H. Peter Anvin <hpa@zytor.com>
This commit is contained in:
parent
57ca281980
commit
7fe0fb941c
5 changed files with 355 additions and 6 deletions
89
aclocal.m4
vendored
89
aclocal.m4
vendored
|
@ -87,6 +87,71 @@ AC_DEFUN(PA_STRUCT_IN_PKTINFO,
|
|||
#include <sys/uio.h>
|
||||
])])
|
||||
|
||||
|
||||
dnl ------------------------------------------------------------------------
|
||||
dnl PA_STRUCT_SOCKADDR_IN6
|
||||
dnl
|
||||
dnl Look for definition of struct sockaddr_in6, which at least has an
|
||||
dnl sin6_addr member
|
||||
dnl
|
||||
AH_TEMPLATE([HAVE_STRUCT_SOCKADDR_IN6],
|
||||
[Define if struct sockaddr_in6 is defined.])
|
||||
|
||||
AC_DEFUN(PA_STRUCT_SOCKADDR_IN6,
|
||||
[AC_CHECK_MEMBER(struct sockaddr_in6.sin6_addr,
|
||||
[
|
||||
AC_DEFINE(HAVE_STRUCT_SOCKADDR_IN6)
|
||||
HAVE_INET6=true;
|
||||
],
|
||||
[
|
||||
HAVE_INET6=false;
|
||||
],
|
||||
[
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
])])
|
||||
|
||||
dnl ------------------------------------------------------------------------
|
||||
dnl PA_STRUCT_ADDRINFO
|
||||
dnl
|
||||
dnl Look for definition of struct addrinfo, which at least has an
|
||||
dnl ai_addr member
|
||||
dnl
|
||||
AH_TEMPLATE([HAVE_STRUCT_ADDRINFO],
|
||||
[Define if struct addrinfo is defined.])
|
||||
|
||||
AC_DEFUN(PA_STRUCT_ADDRINFO,
|
||||
[AC_CHECK_MEMBER(struct addrinfo.ai_addr,
|
||||
[AC_DEFINE(HAVE_STRUCT_ADDRINFO)],
|
||||
[],
|
||||
[
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
])])
|
||||
|
||||
dnl ------------------------------------------------------------------------
|
||||
dnl PA_STRUCT_IN6_PKTINFO
|
||||
dnl
|
||||
dnl Look for definition of struct in6_pktinfo, which at least has an
|
||||
dnl ipi6_addr member
|
||||
dnl
|
||||
AH_TEMPLATE([HAVE_STRUCT_IN6_PKTINFO],
|
||||
[Define if struct in6_pktinfo is defined.])
|
||||
|
||||
AC_DEFUN(PA_STRUCT_IN6_PKTINFO,
|
||||
[AC_CHECK_MEMBER(struct in6_pktinfo.ipi6_addr,
|
||||
[AC_DEFINE(HAVE_STRUCT_IN6_PKTINFO)],
|
||||
[],
|
||||
[
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
])])
|
||||
|
||||
dnl --------------------------------------------------------------------------
|
||||
dnl PA_HAVE_TCPWRAPPERS
|
||||
dnl
|
||||
|
@ -189,3 +254,27 @@ int main()
|
|||
[
|
||||
AC_MSG_RESULT(no)
|
||||
])])
|
||||
|
||||
dnl --------------------------------------------------------------------------
|
||||
dnl PA_SEARCH_LIBS_AND_ADD
|
||||
dnl
|
||||
dnl PA_SEARCH_LIBS_AND_ADD(function, libraries [,function to add])
|
||||
dnl --------------------------------------------------------------------------
|
||||
|
||||
AC_DEFUN(PA_SEARCH_LIBS_AND_ADD,
|
||||
[
|
||||
AH_TEMPLATE(AS_TR_CPP(HAVE_$1), [Define if $1 function was found])
|
||||
AC_SEARCH_LIBS($1, $2,
|
||||
[
|
||||
AC_DEFINE_UNQUOTED(AS_TR_CPP(HAVE_$1))
|
||||
pa_add_$1=false;
|
||||
],
|
||||
[
|
||||
XTRA=true;
|
||||
if test $# -eq 3; then
|
||||
AC_LIBOBJ($3)
|
||||
else
|
||||
AC_LIBOBJ($1)
|
||||
fi
|
||||
pa_add_$1=true;
|
||||
])])
|
||||
|
|
46
config.h
46
config.h
|
@ -106,6 +106,9 @@
|
|||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#ifdef HAVE_NETDB_H
|
||||
#include <netdb.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GETOPT_H
|
||||
#include <getopt.h>
|
||||
|
@ -301,6 +304,49 @@ int dup2(int, int);
|
|||
int daemon(int, int);
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_GETADDRINFO
|
||||
#ifndef HAVE_STRUCT_ADDRINFO
|
||||
struct addrinfo {
|
||||
int ai_flags;
|
||||
int ai_family;
|
||||
int ai_socktype;
|
||||
int ai_protocol;
|
||||
size_t ai_addrlen;
|
||||
struct sockaddr *ai_addr;
|
||||
char *ai_canonname;
|
||||
struct addrinfo *ai_next;
|
||||
};
|
||||
#endif
|
||||
int getaddrinfo(const char *, const char *, const struct addrinfo *,
|
||||
struct addrinfo **);
|
||||
void freeaddrinfo(struct addrinfo *);
|
||||
const char *gai_strerror(int);
|
||||
|
||||
#ifndef AI_CANONNAME
|
||||
#define AI_CANONNAME 0x0002 /* Request for canonical name. */
|
||||
#endif
|
||||
|
||||
#ifndef EAI_NONAME
|
||||
#define EAI_NONAME -2 /* NAME or SERVICE is unknown. */
|
||||
#endif
|
||||
#ifndef EAI_ADDRFAMILY
|
||||
#define EAI_ADDRFAMILY -9 /* Address family for NAME not supported. */
|
||||
#endif
|
||||
#ifndef EAI_MEMORY
|
||||
#define EAI_MEMORY -10 /* Memory allocation failure. */
|
||||
#endif
|
||||
#ifndef EAI_SYSTEM
|
||||
#define EAI_SYSTEM -11 /* System error returned in rrno'. */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_INET_NTOP
|
||||
const char *inet_ntop(int, const void *, char *, socklen_t);
|
||||
#ifndef INET6_ADDRSTRLEN
|
||||
#define INET6_ADDRSTRLEN 48
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* tftp-hpa version and configuration strings */
|
||||
|
||||
#include "version.h"
|
||||
|
|
53
configure.in
53
configure.in
|
@ -52,6 +52,7 @@ AC_CHECK_HEADERS(sys/stat.h)
|
|||
AC_CHECK_HEADERS(sys/time.h)
|
||||
AC_CHECK_HEADERS(sys/types.h)
|
||||
AC_CHECK_HEADERS(arpa/inet.h)
|
||||
AC_CHECK_HEADERS(netdb.h)
|
||||
AC_HEADER_TIME
|
||||
dnl This is needed on some versions of FreeBSD...
|
||||
AC_CHECK_HEADERS(machine/param.h)
|
||||
|
@ -118,9 +119,6 @@ AC_CHECK_TYPES(socklen_t,,,
|
|||
])
|
||||
|
||||
AC_SEARCH_LIBS(socket, [socket ws2_32 wsock32], , [AC_MSG_ERROR(socket library not found)])
|
||||
AC_SEARCH_LIBS(gethostbyname, [nsl resolv], , [AC_MSG_ERROR(gethostbyname not found)])
|
||||
AC_SEARCH_LIBS(inet_aton, [nsl resolv], , [AC_MSG_ERROR(inet_aton not found)])
|
||||
AC_SEARCH_LIBS(herror, [nsl resolv], , [AC_MSG_ERROR(herror not found)])
|
||||
|
||||
AC_CHECK_FUNCS(fcntl)
|
||||
AC_CHECK_FUNCS(setsid)
|
||||
|
@ -137,6 +135,7 @@ AC_CHECK_FUNCS(strtoull)
|
|||
|
||||
PA_MSGHDR_MSG_CONTROL
|
||||
PA_STRUCT_IN_PKTINFO
|
||||
PA_STRUCT_ADDRINFO
|
||||
|
||||
PA_HEADER_DEFINES(fcntl.h, int, O_NONBLOCK)
|
||||
PA_HEADER_DEFINES(fcntl.h, int, O_BINARY)
|
||||
|
@ -153,9 +152,30 @@ SRCROOT=`cd $srcdir && pwd`
|
|||
OBJROOT=`pwd`
|
||||
|
||||
XTRA=false
|
||||
AC_SEARCH_LIBS(xmalloc, iberty, , [XTRA=true; AC_LIBOBJ(xmalloc)])
|
||||
AC_SEARCH_LIBS(xstrdup, iberty, , [XTRA=true; AC_LIBOBJ(xstrdup)])
|
||||
AC_SEARCH_LIBS(bsd_signal, bsd, , [XTRA=true; AC_LIBOBJ(bsdsignal)])
|
||||
PA_SEARCH_LIBS_AND_ADD(xmalloc, iberty)
|
||||
PA_SEARCH_LIBS_AND_ADD(xstrdup, iberty)
|
||||
PA_SEARCH_LIBS_AND_ADD(bsd_signal, bsd, bsdsignal)
|
||||
PA_SEARCH_LIBS_AND_ADD(getaddrinfo, [nsl resolv])
|
||||
if $pa_add_getaddrinfo
|
||||
then
|
||||
AC_SEARCH_LIBS(gethostbyname, [nsl resolv],
|
||||
[AC_SEARCH_LIBS(herror, [nsl resolv], ,
|
||||
[AC_MSG_ERROR(herror not found)])],
|
||||
[AC_MSG_ERROR(gethostbyname not found)])
|
||||
else
|
||||
AC_SEARCH_LIBS(freeaddrinfo, [nsl resolv], ,
|
||||
[AC_MSG_ERROR(getaddrinfo but not freeaddrinfo found)])
|
||||
AC_SEARCH_LIBS(gai_strerror, [nsl resolv], ,
|
||||
[AC_MSG_ERROR(getaddrinfo but not gai_strerror found)])
|
||||
fi
|
||||
|
||||
PA_SEARCH_LIBS_AND_ADD(inet_ntop, [nsl resolv])
|
||||
if $pa_add_inet_ntop
|
||||
then
|
||||
AC_SEARCH_LIBS(inet_ntoa, [nsl resolv], ,
|
||||
[AC_MSG_ERROR(inet_ntoa not found)])
|
||||
fi
|
||||
|
||||
AC_CHECK_FUNCS(daemon, , [XTRA=true; AC_LIBOBJ(daemon)])
|
||||
AC_CHECK_FUNCS(dup2, , [XTRA=true; AC_LIBOBJ(dup2)])
|
||||
if $XTRA
|
||||
|
@ -226,6 +246,27 @@ PA_WITH_BOOL(readline, 1,
|
|||
TFTP_LIBS="$LIBS $XTRALIBS"
|
||||
LIBS="$common_libs"
|
||||
|
||||
dnl
|
||||
dnl Check for IPV6 and disable-ipv6
|
||||
dnl
|
||||
PA_STRUCT_SOCKADDR_IN6
|
||||
AC_MSG_CHECKING([for IPv6 support])
|
||||
PA_WITH_BOOL(ipv6, 1,
|
||||
[ --without-ipv6 disable the support for IPv6],
|
||||
[
|
||||
if $HAVE_INET6
|
||||
then
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_IPV6, 1, [Define if IPv6 support is enabled.])
|
||||
PA_STRUCT_IN6_PKTINFO
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
AC_MSG_WARN([*** we do not have required IPv6 structs - IPv6 will be disabled])
|
||||
fi
|
||||
],
|
||||
[AC_MSG_RESULT(disabled)])
|
||||
|
||||
|
||||
AC_SUBST(SRCROOT)
|
||||
AC_SUBST(OBJROOT)
|
||||
|
||||
|
|
121
lib/getaddrinfo.c
Normal file
121
lib/getaddrinfo.c
Normal file
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
* getaddrinfo.c
|
||||
*
|
||||
* Simple version of getaddrinfo()
|
||||
*
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
extern int errno;
|
||||
extern int h_errno;
|
||||
|
||||
void freeaddrinfo(struct addrinfo *res)
|
||||
{
|
||||
if (!res)
|
||||
return;
|
||||
if (res->ai_next)
|
||||
freeaddrinfo(res->ai_next);
|
||||
if (res->ai_addr)
|
||||
free(res->ai_addr);
|
||||
if (res->ai_canonname)
|
||||
free(res->ai_canonname);
|
||||
free(res);
|
||||
}
|
||||
|
||||
int getaddrinfo(const char *node, const char *service, const struct addrinfo *hints,
|
||||
struct addrinfo **res)
|
||||
{
|
||||
struct hostent *host;
|
||||
struct sockaddr *sa;
|
||||
int err, size = 0;
|
||||
|
||||
if ((!node) || (!res)) {
|
||||
errno = EINVAL;
|
||||
return EAI_SYSTEM;
|
||||
}
|
||||
*res = NULL;
|
||||
/* we do not support service in this version */
|
||||
if (service) {
|
||||
errno = EINVAL;
|
||||
return EAI_SYSTEM;
|
||||
}
|
||||
host = gethostbyname(node);
|
||||
if (!host)
|
||||
return EAI_NONAME;
|
||||
if (hints) {
|
||||
if (hints->ai_family != AF_UNSPEC) {
|
||||
if (hints->ai_family != host->h_addrtype)
|
||||
return EAI_ADDRFAMILY;
|
||||
}
|
||||
}
|
||||
*res = malloc(sizeof(struct addrinfo));
|
||||
if (!*res) {
|
||||
return EAI_MEMORY;
|
||||
}
|
||||
memset(*res, 0, sizeof(struct addrinfo));
|
||||
(*res)->ai_family = host->h_addrtype;
|
||||
if (host->h_length) {
|
||||
if (host->h_addrtype == AF_INET)
|
||||
size = sizeof(struct sockaddr_in);
|
||||
#ifdef HAVE_IPV6
|
||||
else if (host->h_addrtype == AF_INET6)
|
||||
size = sizeof(struct sockaddr_in6);
|
||||
#endif
|
||||
else {
|
||||
free(*res);
|
||||
*res = NULL;
|
||||
return EAI_ADDRFAMILY;
|
||||
}
|
||||
sa = malloc(size);
|
||||
if (!sa) {
|
||||
free(*res);
|
||||
*res = NULL;
|
||||
return EAI_MEMORY;
|
||||
}
|
||||
memset(sa, 0, size);
|
||||
(*res)->ai_addr = sa;
|
||||
(*res)->ai_addrlen = size;
|
||||
sa->sa_family = host->h_addrtype;
|
||||
if (host->h_addrtype == AF_INET)
|
||||
memcpy(&((struct sockaddr_in *)sa)->sin_addr, host->h_addr, host->h_length);
|
||||
#ifdef HAVE_IPV6
|
||||
else
|
||||
memcpy(&((struct sockaddr_in6 *)sa)->sin6_addr, host->h_addr, host->h_length);
|
||||
#endif
|
||||
}
|
||||
if (host->h_name)
|
||||
(*res)->ai_canonname = strdup(host->h_name);
|
||||
|
||||
/* we only handle the first address entry and do not build a list now */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const char *gai_strerror(int errcode)
|
||||
{
|
||||
const char *s = NULL;
|
||||
|
||||
switch(errcode) {
|
||||
case 0:
|
||||
s = "no error";
|
||||
break;
|
||||
case EAI_MEMORY:
|
||||
s = "no memory";
|
||||
break;
|
||||
case EAI_SYSTEM:
|
||||
s = strerror(errno);
|
||||
break;
|
||||
case EAI_NONAME:
|
||||
s = hstrerror(h_errno);
|
||||
break;
|
||||
case EAI_ADDRFAMILY:
|
||||
s = "address does not match address family";
|
||||
break;
|
||||
default:
|
||||
s = "unknown error code";
|
||||
break;
|
||||
}
|
||||
return s;
|
||||
}
|
52
lib/inet_ntop.c
Normal file
52
lib/inet_ntop.c
Normal file
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* inet_ntop.c
|
||||
*
|
||||
* Simple version of inet_ntop()
|
||||
*
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
extern int errno;
|
||||
|
||||
const char *inet_ntop(int af, const void *src,
|
||||
char *dst, socklen_t cnt)
|
||||
{
|
||||
char *p;
|
||||
|
||||
switch(af) {
|
||||
case AF_INET:
|
||||
p = inet_ntoa(*((struct in_addr *)src));
|
||||
if (p) {
|
||||
if (cnt <= strlen(p)) {
|
||||
errno = ENOSPC;
|
||||
dst = NULL;
|
||||
} else
|
||||
strcpy(dst, p);
|
||||
} else
|
||||
dst = NULL;
|
||||
break;
|
||||
#ifdef HAVE_IPV6
|
||||
case AF_INET6:
|
||||
if (cnt < 40) {
|
||||
errno = ENOSPC;
|
||||
dst = NULL;
|
||||
} else {
|
||||
struct in6_addr *a = src;
|
||||
int i;
|
||||
|
||||
p = (char *)dst;
|
||||
/* we do not compress :0: to :: */
|
||||
for (i = 0; i < 8; i++)
|
||||
p += sprintf(p, "%x:", ntohs(a->s6_addr16[i]));
|
||||
p--;
|
||||
*p = 0;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
errno = EAFNOSUPPORT;
|
||||
dst = NULL;
|
||||
}
|
||||
return dst;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue