-/* $OpenBSD: parse.y,v 1.121 2008/07/19 11:38:54 reyk Exp $ */
+/* $OpenBSD: parse.y,v 1.122 2008/07/22 23:17:37 reyk Exp $ */
/*
* Copyright (c) 2007, 2008 Reyk Floeter <reyk@openbsd.org>
%token ON PATH PORT PREFORK PROTO QUERYSTR REAL REDIRECT RELAY REMOVE TRAP
%token REQUEST RESPONSE RETRY RETURN ROUNDROBIN SACK SCRIPT SEND SESSION
%token SOCKET SSL STICKYADDR STYLE TABLE TAG TCP TIMEOUT TO UPDATES URL
-%token VIRTUAL WITH ERROR ROUTE TRANSPARENT PARENT
+%token VIRTUAL WITH ERROR ROUTE TRANSPARENT PARENT INET INET6
%token <v.string> STRING
%token <v.number> NUMBER
%type <v.string> interface hostname table
}
tableport = h->port;
}
- | forwardmode TO forwardspec interface {
+ | forwardmode TO forwardspec interface dstaf {
rlay->rl_conf.fwdmode = $1;
switch ($1) {
case FWD_NORMAL:
| HASH { $$ = RELAY_DSTMODE_HASH; }
;
+dstaf : /* empty */ {
+ rlay->rl_conf.dstaf.ss_family = AF_UNSPEC;
+ }
+ | INET {
+ rlay->rl_conf.dstaf.ss_family = AF_INET;
+ }
+ | INET6 STRING {
+ struct sockaddr_in6 *sin6;
+
+ sin6 = (struct sockaddr_in6 *)&rlay->rl_conf.dstaf;
+ if (inet_pton(AF_INET6, $2, &sin6->sin6_addr) == -1) {
+ yyerror("invalid ipv6 address %s", $2);
+ free($2);
+ YYERROR;
+ }
+ free($2);
+
+ sin6->sin6_family = AF_INET6;
+ sin6->sin6_len = sizeof(*sin6);
+ }
+ ;
+
interface : /*empty*/ { $$ = NULL; }
| INTERFACE STRING { $$ = $2; }
;
{ "host", HOST },
{ "icmp", ICMP },
{ "include", INCLUDE },
+ { "inet", INET },
+ { "inet6", INET6 },
{ "interface", INTERFACE },
{ "interval", INTERVAL },
{ "ip", IP },
-/* $OpenBSD: relay.c,v 1.94 2008/07/16 15:02:19 reyk Exp $ */
+/* $OpenBSD: relay.c,v 1.95 2008/07/22 23:17:37 reyk Exp $ */
/*
* Copyright (c) 2006, 2007, 2008 Reyk Floeter <reyk@openbsd.org>
relay_connect(struct session *con)
{
struct relay *rlay = (struct relay *)con->se_relay;
- int bnds = -1;
+ int bnds = -1, ret;
if (gettimeofday(&con->se_tv_start, NULL))
return (-1);
bnds = con->se_bnds;
}
+ /* Do the IPv4-to-IPv6 or IPv6-to-IPv4 translation if requested */
+ if (rlay->rl_conf.dstaf.ss_family != AF_UNSPEC) {
+ if (con->se_out.ss.ss_family == AF_INET &&
+ rlay->rl_conf.dstaf.ss_family == AF_INET6)
+ ret = map4to6(&con->se_out.ss, &rlay->rl_conf.dstaf);
+ else if (con->se_out.ss.ss_family == AF_INET6 &&
+ rlay->rl_conf.dstaf.ss_family == AF_INET)
+ ret = map6to4(&con->se_out.ss);
+ else
+ ret = 0;
+ if (ret != 0) {
+ log_debug("relay_connect: mapped to invalid address");
+ return (-1);
+ }
+ }
+
retry:
if ((con->se_out.s = relay_socket_connect(&con->se_out.ss,
con->se_out.port, rlay->rl_proto, bnds)) == -1) {
-/* $OpenBSD: relayd.c,v 1.78 2008/07/09 14:06:44 reyk Exp $ */
+/* $OpenBSD: relayd.c,v 1.79 2008/07/22 23:17:37 reyk Exp $ */
/*
* Copyright (c) 2007, 2008 Reyk Floeter <reyk@openbsd.org>
close(s);
return (-1);
}
+
+int
+map6to4(struct sockaddr_storage *in6)
+{
+ struct sockaddr_storage out4;
+ struct sockaddr_in *sin4 = (struct sockaddr_in *)&out4;
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)in6;
+
+ bzero(sin4, sizeof(*sin4));
+ sin4->sin_len = sizeof(*sin4);
+ sin4->sin_family = AF_INET;
+ sin4->sin_port = sin6->sin6_port;
+
+ bcopy(&sin6->sin6_addr.s6_addr[12], &sin4->sin_addr.s_addr,
+ sizeof(sin4->sin_addr));
+
+ if (sin4->sin_addr.s_addr == INADDR_ANY ||
+ sin4->sin_addr.s_addr == INADDR_BROADCAST ||
+ IN_MULTICAST(ntohl(sin4->sin_addr.s_addr)))
+ return (-1);
+
+ bcopy(&out4, in6, sizeof(*in6));
+
+ return (0);
+}
+
+int
+map4to6(struct sockaddr_storage *in4, struct sockaddr_storage *map)
+{
+ struct sockaddr_storage out6;
+ struct sockaddr_in *sin4 = (struct sockaddr_in *)in4;
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&out6;
+ struct sockaddr_in6 *map6 = (struct sockaddr_in6 *)map;
+
+ if (sin4->sin_addr.s_addr == INADDR_ANY ||
+ sin4->sin_addr.s_addr == INADDR_BROADCAST ||
+ IN_MULTICAST(ntohl(sin4->sin_addr.s_addr)))
+ return (-1);
+
+ bcopy(map6, sin6, sizeof(*sin6));
+ sin6->sin6_len = sizeof(*sin6);
+ sin6->sin6_family = AF_INET6;
+ sin6->sin6_port = sin4->sin_port;
+
+ bcopy(&sin4->sin_addr.s_addr, &sin6->sin6_addr.s6_addr[12],
+ sizeof(sin4->sin_addr));
+
+ bcopy(&out6, in4, sizeof(*in4));
+
+ return (0);
+}
-.\" $OpenBSD: relayd.conf.5,v 1.90 2008/07/19 16:35:50 jmc Exp $
+.\" $OpenBSD: relayd.conf.5,v 1.91 2008/07/22 23:17:37 reyk Exp $
.\"
.\" Copyright (c) 2006, 2007 Reyk Floeter <reyk@openbsd.org>
.\" Copyright (c) 2006, 2007 Pierre-Yves Ritschard <pyr@openbsd.org>
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: July 19 2008 $
+.Dd $Mdocdate: July 22 2008 $
.Dt RELAYD.CONF 5
.Os
.Sh NAME
.Ic forward to
.Ar address
.Op Ic port Ar port
-.Op Ic retry Ar number
+.Ar options ...
.Xc
Specify the address and port of the target host to connect to.
If the
option is not specified, the port from the
.Ic listen on
directive will be used.
-.Pp
Use the
.Ic transparent
keyword to enable fully-transparent mode; the source address of the
client will be retained in this case.
.Pp
-The optional host retry option will be used as a tolerance for failed
+The following options may be specified for forward directives:
+.Pp
+.Bl -tag -width Ds
+.It Ic retry Ar number
+The optional host
+.Ic retry
+option will be used as a tolerance for failed
host connections; the connection will be retried for
.Ar number
more times.
+.It Ic inet
+If the requested destination is an IPv6 address,
+.Xr relayd 8
+will forward the connection to an IPv4 address which is determined by
+the last 4 octets of the original IPv6 destination.
+For example, if the original IPv6 destination address is
+2001:db8:7395:ffff::a01:101, the session is relayed to the IPv4
+address 10.1.1.1 (a01:101).
+.It Ic inet6 Ar address-prefix
+If the requested destination is an IPv4 address,
+.Xr relayd 8
+will forward the connection to an IPv6 address which is determined by
+setting the last 4 octets of the specified IPv6
+.Ar address-prefix
+to the 4 octets of the original IPv4 destination.
+For example, if the original IPv4 destination address is 10.1.1.1 and
+the specified address prefix is 2001:db8:7395:ffff::, the session is
+relayed to the IPv6 address 2001:db8:7395:ffff::a01:101.
+.El
.It Xo
.Ic forward to
.Aq Ar table
.It Xo
.Ic forward to
.Ic nat lookup
-.Op Ic retry Ar number
+.Ar options ...
.Xc
When redirecting connections with an
.Ar rdr
-/* $OpenBSD: relayd.h,v 1.108 2008/07/19 11:38:54 reyk Exp $ */
+/* $OpenBSD: relayd.h,v 1.109 2008/07/22 23:17:37 reyk Exp $ */
/*
* Copyright (c) 2006, 2007 Pierre-Yves Ritschard <pyr@openbsd.org>
objid_t dsttable;
struct sockaddr_storage ss;
struct sockaddr_storage dstss;
+ struct sockaddr_storage dstaf;
struct timeval timeout;
enum forwardmode fwdmode;
};
struct protonode *);
int protonode_add(enum direction, struct protocol *,
struct protonode *);
+int map6to4(struct sockaddr_storage *);
+int map4to6(struct sockaddr_storage *, struct sockaddr_storage *);
/* carp.c */
int carp_demote_init(char *, int);