IPv6 support.

Add $FreeBSD$.
This commit is contained in:
Hajimu UMEMOTO 2000-05-25 16:38:22 +00:00
parent f1beb78299
commit 84861c13f9
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=60926
7 changed files with 242 additions and 98 deletions

View file

@ -1,6 +1,8 @@
/* config.h. Generated automatically by configure. */
/* Configuration header file for Taylor UUCP. -*- C -*- */
/* $FreeBSD$ */
/* If your compiler does not use const correctly, then undefine it
here. This #undef is commented out by the configure script if it
determines that const is supported. */
@ -217,6 +219,9 @@
is on AIX. */
#define HAVE_TXADDCD 0
/* Set HAVE_SOCKADDR_SA_LEN to 1 if struct sockaddr has sa_len member. */
#define HAVE_SOCKADDR_SA_LEN 1
/* There are now a number of functions to check for. For each of
these, the macro HAVE_FUNC should be set to 1 if your system has
FUNC. For example, HAVE_VFPRINTF should be set to 1 if your system
@ -288,6 +293,10 @@
#define HAVE_STRRCHR 1
#define HAVE_RINDEX 1
/* If neither of these functions exists, you should add getaddrinfo.o to
lib/Makefile. */
#define HAVE_GETADDRINFO 1
/* There are also Unix specific functions which are replaced in the
subdirectory unix. If they are missing, the configure script will
automatically add them to unix/Makefile to force them to be

View file

@ -29,6 +29,8 @@
c/o Cygnus Support, 48 Grove Street, Somerville, MA 02144.
*/
/* $FreeBSD$ */
#ifndef UUCONF_H
#define UUCONF_H
@ -417,6 +419,8 @@ struct uuconf_tcp_port
/* The TCP port number to use. May be a name or a number. May be
NULL, in which case "uucp" is looked up using getservbyname. */
char *uuconf_zport;
/* Address family to use for a TCP connection. */
int uuconf_zfamily;
/* A NULL terminated sequence of dialer/token pairs (element 0 is a
dialer name, element 1 is a token, etc.) May be NULL. */
char **uuconf_pzdialer;

View file

@ -1,4 +1,7 @@
\input texinfo @c -*-texinfo-*-
@c $FreeBSD$
@c %**start of header
@setfilename uucp.info
@settitle Taylor UUCP
@ -5204,6 +5207,13 @@ string @samp{uucp} is looked up in @file{/etc/services}. If it is not
found, port number 540 (the standard UUCP-over-TCP port number) will be
used.
@item family @var{string} [ tcp only ]
@findex family
Name the protocol family to use. Available value is @samp{inet} for
IPv4 only, @samp{inet6} for IPv6 only, or @samp{inet46} for both IPv4
and IPv6. The default is @samp{inet46}.
@item push @var{strings} [ tli only ]
@findex push
@ -5474,7 +5484,12 @@ Files}), add the line @samp{port type tcp} to the entry in the
@samp{uucp} in @file{/etc/services}; if the @samp{uucp} service is not
defined, port 540 will be used. You can set the port number to use with
the command @samp{port service @var{xxx}}, where @var{xxx} can be either
a number or a name to look up in @file{/etc/services}. You can specify
a number or a name to look up in @file{/etc/services}. By default UUCP
will determine the protocol family by querying DNS; if the AAAA record
is found, IPv6 will be used, and if not found, IPv4 will be used. You
can set the protocol family to use with the command @samp{port family
@var{xxx}}, where @var{xxx} can be @samp{inet} for IPv4 only,
@samp{inet6} for IPv6 only or @samp{inet46} for both. You can specify
the address of the remote host with @samp{address @var{a.b.c}}; if you
don't give an address, the remote system name will be used. You should
give an explicit chat script for the system when you use TCP; the
@ -5506,6 +5521,10 @@ be called at any time, over TCP, using port number @samp{uucp} (as found
in @file{/etc/services}; this may be specified as a number), using
remote host @file{@var{host}.@var{domain}}, with some chat script.
@samp{port family @var{xxx}} command is not supported by V2
configuration files or HDB configuration files. So, with these
configuration files, IPv6 is disabled for compatibility reason.
@node TCP Server, , TCP Client, UUCP Over TCP
@subsection Running a TCP Server
@ -5525,6 +5544,15 @@ child for each one. Each connection will be prompted with @samp{login:}
and @samp{Password:}; the results will be checked against the UUCP (not
the system) password file (@pxref{Configuration File Names}).
By default UUCP will listen on both IPv4 and IPv6. You can set the
protocol family to listen with the command @samp{port family @var{xxx}},
where @var{xxx} can be @samp{inet} for IPv4 only, @samp{inet6} for IPv6
only or @samp{inet46} for both IPv4 and IPv6.
@samp{port family @var{xxx}} command is not supported by V2
configuration files or HDB configuration files. So, with these
configuration files, IPv6 is disabled for compatibility reason.
Another way to run a UUCP TCP server is to use the BSD @code{uucpd}
program.

View file

@ -63,7 +63,7 @@ const char tcp_rcsid[] = "$FreeBSD$";
interface. */
/* The normal "uucp" port number. */
#define IUUCP_PORT (540)
#define IUUCP_PORT "540"
/* Local functions. */
static void utcp_free P((struct sconnection *qconn));
@ -78,7 +78,9 @@ static boolean ftcp_dial P((struct sconnection *qconn, pointer puuconf,
const char *zphone,
struct uuconf_dialer *qdialer,
enum tdialerfound *ptdialer));
static int itcp_port_number P((const char *zport));
static int itcp_getaddrinfo P((const char *zhost, const char *zport,
const struct addrinfo *hints,
struct addrinfo **res));
/* The command table for a TCP connection. */
static const struct sconncmds stcpcmds =
@ -131,34 +133,13 @@ utcp_free (qconn)
{
xfree (qconn->psysdep);
}
/* Open a TCP connection. If the fwait argument is TRUE, we are
running as a server. Otherwise we are just trying to reach another
system. */
static boolean
ftcp_open (qconn, ibaud, fwait)
struct sconnection *qconn;
long ibaud;
boolean fwait;
utcp_init (qsysdep)
struct ssysdep_conn *qsysdep;
{
struct ssysdep_conn *qsysdep;
struct sockaddr_in s;
const char *zport;
uid_t ieuid;
boolean fswap;
ulog_device ("TCP");
qsysdep = (struct ssysdep_conn *) qconn->psysdep;
qsysdep->o = socket (AF_INET, SOCK_STREAM, 0);
if (qsysdep->o < 0)
{
ulog (LOG_ERROR, "socket: %s", strerror (errno));
return FALSE;
}
if (!qsysdep)
return FALSE;
if (fcntl (qsysdep->o, F_SETFD,
fcntl (qsysdep->o, F_GETFD, 0) | FD_CLOEXEC) < 0)
{
@ -176,6 +157,32 @@ ftcp_open (qconn, ibaud, fwait)
qsysdep->o = -1;
return FALSE;
}
}
/* Open a TCP connection. If the fwait argument is TRUE, we are
running as a server. Otherwise we are just trying to reach another
system. */
static boolean
ftcp_open (qconn, ibaud, fwait)
struct sconnection *qconn;
long ibaud;
boolean fwait;
{
struct ssysdep_conn *qsysdep;
struct addrinfo hints, *res, *res0;
struct sockaddr_storage s;
const char *zport;
int zfamily;
uid_t ieuid;
boolean fswap;
int err;
ulog_device ("TCP");
qsysdep = (struct ssysdep_conn *) qconn->psysdep;
qsysdep->o = -1;
/* We save our process ID in the qconn structure. This is checked
in ftcp_close. */
@ -190,11 +197,68 @@ ftcp_open (qconn, ibaud, fwait)
From this point on if the server gets an error we exit; we only
return if we have received a connection. It would be more robust
to respawn the server if it fails; someday. */
bzero ((pointer) &s, sizeof s);
s.sin_family = AF_INET;
zport = qconn->qport->uuconf_u.uuconf_stcp.uuconf_zport;
s.sin_port = itcp_port_number (zport);
s.sin_addr.s_addr = htonl (INADDR_ANY);
zfamily = qconn->qport->uuconf_u.uuconf_stcp.uuconf_zfamily;
memset (&hints, 0, sizeof(hints));
hints.ai_family = zfamily;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
if ((err = itcp_getaddrinfo (NULL, zport, &hints, &res0)) != 0)
{
ulog (LOG_ERROR, "getaddrinfo (NULL, %s): %s",
zport, gai_strerror (err));
return FALSE;
}
#if HAVE_GETADDRINFO
if (zfamily == PF_UNSPEC)
{
for (res = res0; res; res = res->ai_next)
{
if (res->ai_family == AF_INET6)
{
qsysdep->o = socket (res->ai_family, res->ai_socktype,
res->ai_protocol);
if (qsysdep->o >= 0)
break;
}
}
}
#endif
if (qsysdep->o < 0)
{
for (res = res0; res; res = res->ai_next)
{
qsysdep->o = socket (res->ai_family, res->ai_socktype,
res->ai_protocol);
if (qsysdep->o >= 0)
break;
}
if (qsysdep->o < 0)
{
freeaddrinfo (res);
ulog (LOG_ERROR, "socket: %s", strerror (errno));
return FALSE;
}
}
#ifdef IPV6_BINDV6ONLY
if (res->ai_family == AF_INET6)
{
int flag = (zfamily == PF_UNSPEC) ? 0 : 1;
if (setsockopt (qsysdep->o, IPPROTO_IPV6, IPV6_BINDV6ONLY,
(char *)&flag, sizeof (flag)) < 0)
{
freeaddrinfo (res);
ulog (LOG_FATAL, "setsockopt: %s", strerror (errno));
return FALSE;
}
}
#endif
if (!utcp_init (qsysdep))
{
freeaddrinfo (res);
return FALSE;
}
/* Swap to our real user ID when doing the bind call. This will
permit the server to use privileged TCP ports when invoked by
@ -208,16 +272,19 @@ ftcp_open (qconn, ibaud, fwait)
{
(void) close (qsysdep->o);
qsysdep->o = -1;
freeaddrinfo (res);
return FALSE;
}
}
if (bind (qsysdep->o, (struct sockaddr *) &s, sizeof s) < 0)
if (bind (qsysdep->o, res->ai_addr, res->ai_addrlen) < 0)
{
freeaddrinfo (res);
if (fswap)
(void) fsuucp_perms ((long) ieuid);
ulog (LOG_FATAL, "bind: %s", strerror (errno));
}
freeaddrinfo (res);
/* Now swap back to the uucp user ID. */
if (fswap)
@ -333,8 +400,8 @@ ftcp_dial (qconn, puuconf, qsys, zphone, qdialer, ptdialer)
{
struct ssysdep_conn *qsysdep;
const char *zhost;
struct hostent *q;
struct sockaddr_in s;
struct addrinfo hints, *res, *res0;
int err, connected = FALSE;
const char *zport;
char **pzdialer;
@ -354,37 +421,38 @@ ftcp_dial (qconn, puuconf, qsys, zphone, qdialer, ptdialer)
}
errno = 0;
q = gethostbyname ((char *) zhost);
if (q != NULL)
{
s.sin_family = q->h_addrtype;
memcpy (&s.sin_addr.s_addr, q->h_addr, (size_t) q->h_length);
}
else
{
if (errno != 0)
{
ulog (LOG_ERROR, "gethostbyname (%s): %s", zhost, strerror (errno));
return FALSE;
}
s.sin_family = AF_INET;
s.sin_addr.s_addr = inet_addr ((char *) zhost);
if ((long) s.sin_addr.s_addr == (long) -1)
{
ulog (LOG_ERROR, "%s: unknown host name", zhost);
return FALSE;
}
}
zport = qconn->qport->uuconf_u.uuconf_stcp.uuconf_zport;
s.sin_port = itcp_port_number (zport);
memset (&hints, 0, sizeof(hints));
hints.ai_family = qconn->qport->uuconf_u.uuconf_stcp.uuconf_zfamily;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = 0;
if ((err = itcp_getaddrinfo (zhost, zport, &hints, &res0)) != 0)
{
ulog (LOG_ERROR, "getaddrinfo (%s, %s): %s",
zhost, zport, gai_strerror (err));
return FALSE;
}
if (connect (qsysdep->o, (struct sockaddr *) &s, sizeof s) < 0)
for (res = res0; res; res = res->ai_next)
{
qsysdep->o = socket (res->ai_family, res->ai_socktype, res->ai_protocol);
if (qsysdep->o < 0)
continue;
if (connect (qsysdep->o, res->ai_addr, res->ai_addrlen) >= 0)
{
connected = TRUE;
break;
}
close (qsysdep->o);
}
freeaddrinfo (res0);
if (!connected)
{
ulog (LOG_ERROR, "connect: %s", strerror (errno));
return FALSE;
}
if (!utcp_init (qsysdep))
return FALSE;
/* Handle the dialer sequence, if any. */
pzdialer = qconn->qport->uuconf_u.uuconf_stcp.uuconf_pzdialer;
@ -398,47 +466,18 @@ ftcp_dial (qconn, puuconf, qsys, zphone, qdialer, ptdialer)
return TRUE;
}
/* Get the port number given a name. The argument will almost always
be "uucp" so we cache that value. The return value is always in
network byte order. This returns -1 on error. */
static int
itcp_port_number (zname)
const char *zname;
itcp_getaddrinfo (zhost, zport, hints, res)
const char *zhost, *zport;
const struct addrinfo *hints;
struct addrinfo **res;
{
boolean fuucp;
static int iuucp;
int i;
char *zend;
struct servent *q;
int err;
fuucp = strcmp (zname, "uucp") == 0;
if (fuucp && iuucp != 0)
return iuucp;
/* Try it as a number first. */
i = strtol ((char *) zname, &zend, 10);
if (i != 0 && *zend == '\0')
return htons (i);
q = getservbyname ((char *) zname, (char *) "tcp");
if (q == NULL)
{
/* We know that the "uucp" service should be 540, even if isn't
in /etc/services. */
if (fuucp)
{
iuucp = htons (IUUCP_PORT);
return iuucp;
}
ulog (LOG_ERROR, "getservbyname (%s): %s", zname, strerror (errno));
return -1;
}
if (fuucp)
iuucp = q->s_port;
return q->s_port;
if ((err = getaddrinfo (zhost, zport, hints, res)) != EAI_SERVICE ||
strcmp(zport, "uucp") != 0)
return err;
return getaddrinfo (zhost, IUUCP_PORT, hints, res);
}
#endif /* HAVE_TCP */

View file

@ -29,6 +29,7 @@
const char _uuconf_hport_rcsid[] = "$FreeBSD$";
#endif
#include <sys/socket.h>
#include <errno.h>
#include <ctype.h>
@ -217,6 +218,19 @@ uuconf_hdb_find_port (pglobal, zname, ibaud, ihighbaud, pifn, pinfo, qport)
| UUCONF_RELIABLE_EIGHT | UUCONF_RELIABLE_FULLDUPLEX
| UUCONF_RELIABLE_SPECIFIED);
qport->uuconf_u.uuconf_stcp.uuconf_zport = pzsplit[1];
/* I leave with IPv4 only for compatibility reason. If
you wish to use IPv6, please try Taylor UUCP
configuration instead. If you still wish to use IPv6
with HDB configuration, re-make with INET6 defined.
In this case, you cannot specify the protocol family
in HDB configuration file. */
#ifdef INET6
qport->uuconf_u.uuconf_stcp.uuconf_zfamily = PF_UNSPEC;
#else
qport->uuconf_u.uuconf_stcp.uuconf_zfamily = PF_INET;
#endif
ppzdialer = &qport->uuconf_u.uuconf_stcp.uuconf_pzdialer;
}
else if (ctoks >= 5

View file

@ -29,6 +29,7 @@
const char _uuconf_tportc_rcsid[] = "$FreeBSD$";
#endif
#include <sys/socket.h>
#include <errno.h>
static int ipproto_param P((pointer pglobal, int argc, char **argv,
@ -37,6 +38,8 @@ static int ipbaud_range P((pointer pglobal, int argc, char **argv,
pointer pvar, pointer pinfo));
static int ipdialer P((pointer pglobal, int argc, char **argv, pointer pvar,
pointer pinfo));
static int ipfamily P((pointer pglobal, int argc, char **argv, pointer pvar,
pointer pinfo));
static int ipcunknown P((pointer pglobal, int argc, char **argv,
pointer pvar, pointer pinfo));
@ -151,6 +154,9 @@ static const struct cmdtab_offset asPtcp_cmds[] =
{ "service", UUCONF_CMDTABTYPE_STRING,
offsetof (struct uuconf_port, uuconf_u.uuconf_stcp.uuconf_zport),
NULL },
{ "family", UUCONF_CMDTABTYPE_FN | 0,
offsetof (struct uuconf_port, uuconf_u.uuconf_stcp.uuconf_zfamily),
ipfamily },
{ "dialer-sequence", UUCONF_CMDTABTYPE_FULLSTRING,
offsetof (struct uuconf_port, uuconf_u.uuconf_stcp.uuconf_pzdialer),
NULL },
@ -279,6 +285,7 @@ _uuconf_iport_cmd (qglobal, argc, argv, qport)
break;
case UUCONF_PORTTYPE_TCP:
qport->uuconf_u.uuconf_stcp.uuconf_zport = (char *) "uucp";
qport->uuconf_u.uuconf_stcp.uuconf_zfamily = PF_UNSPEC;
qport->uuconf_u.uuconf_stcp.uuconf_pzdialer = NULL;
qport->uuconf_ireliable = (UUCONF_RELIABLE_SPECIFIED
| UUCONF_RELIABLE_ENDTOEND
@ -489,6 +496,35 @@ ipdialer (pglobal, argc, argv, pvar, pinfo)
return iret;
}
}
/* Handle a "family" commands. The first argument is "inet" for
PF_INET or "inet6" for PF_INET6 */
/*ARGSUSED*/
static int
ipfamily (pglobal, argc, argv, pvar, pinfo)
pointer pglobal;
int argc;
char **argv;
pointer pvar;
pointer pinfo;
{
int *pzfamily = (int *) pvar;
if (argc < 2)
return UUCONF_SYNTAX_ERROR | UUCONF_CMDTABRET_EXIT;
if (!strcmp(argv[1], "inet"))
*pzfamily = PF_INET;
#if HAVE_GETADDRINFO
else if (!strcmp(argv[1], "inet6"))
*pzfamily = PF_INET6;
#endif
else if (!strcmp(argv[1], "inet46"))
*pzfamily = PF_UNSPEC;
else
return UUCONF_SYNTAX_ERROR | UUCONF_CMDTABRET_EXIT;
return UUCONF_CMDTABRET_KEEP;
}
/* Give an error for an unknown port command. */

View file

@ -29,6 +29,7 @@
const char _uuconf_vsinfo_rcsid[] = "$FreeBSD$";
#endif
#include <sys/socket.h>
#include <errno.h>
#include <ctype.h>
@ -271,6 +272,19 @@ _uuconf_iv2_system_internal (qglobal, zsystem, qsys)
else
qset->uuconf_qport->uuconf_u.uuconf_stcp.uuconf_zport
= pzsplit[3];
/* I leave with IPv4 only for compatibility reason. If you
wish to use IPv6, please try Taylor UUCP configuration
instead. If you still wish to use IPv6 with V2
configuration, re-make with INET6 defined. In this case,
you cannot specify the protocol family in V2
configuration file. */
#ifdef INET6
qset->uuconf_qport->uuconf_u.uuconf_stcp.uuconf_zfamily = PF_UNSPEC;
#else
qset->uuconf_qport->uuconf_u.uuconf_stcp.uuconf_zfamily = PF_INET;
#endif
qset->uuconf_qport->uuconf_u.uuconf_stcp.uuconf_pzdialer = NULL;
}