svn commit: r359698 - in stable/11: share/man/man4 sys/netgraph
Eugene Grosbein
eugen at FreeBSD.org
Tue Apr 7 16:47:36 UTC 2020
Author: eugen
Date: Tue Apr 7 16:47:35 2020
New Revision: 359698
URL: https://svnweb.freebsd.org/changeset/base/359698
Log:
MFC r342168,357786: Allow ng_nat to be attached to a ethernet interface
Allow ng_nat to be attached to a ethernet interface directly via ng_ether(4)
or the likes. Add new control message types: setdlt and getdlt to switch
from default DLT_RAW (no encapsulation) to DLT_EN10MB (ethernet).
Submitted by: sobomax
Reviewed by: glebius
Differential Revision: https://reviews.freebsd.org/D18535
Relnotes: yes
Modified:
stable/11/share/man/man4/ng_nat.4
stable/11/sys/netgraph/ng_nat.c
stable/11/sys/netgraph/ng_nat.h
Directory Properties:
stable/11/ (props changed)
Modified: stable/11/share/man/man4/ng_nat.4
==============================================================================
--- stable/11/share/man/man4/ng_nat.4 Tue Apr 7 16:44:14 2020 (r359697)
+++ stable/11/share/man/man4/ng_nat.4 Tue Apr 7 16:47:35 2020 (r359698)
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd March 21, 2013
+.Dd December 12, 2018
.Dt NG_NAT 4
.Os
.Sh NAME
@@ -264,6 +264,38 @@ from its
.Xr libalias
instance, the corresponding field is returned as
.Va UINT32_MAX .
+.It Dv NGM_NAT_SET_DLT Pq Ic setdlt
+Sets the data link type on the
+.Va in
+and
+.Va out
+hooks.
+Currently, supported types are
+.Cm DLT_RAW
+(raw IP datagrams , no offset applied, the default) and
+.Cm DLT_EN10MB
+(Ethernet). DLT_ definitions can be found in
+.In net/bpf.h .
+If you want to work on the
+.Xr ipfw 8
+level you must use no additional offset by specifying
+.Cm DLT_RAW .
+If, however, you attach
+.Nm
+to a network interface directly and
+.Cm EN10MB
+is specified, then the extra offset will be applied to take into account
+link-level header.
+In this mode the
+.Nm
+would also inspect appropriate type field in the Ethernet header and
+pass-through any datagrams that are not IP packets.
+.It Dv NGM_NAT_GET_DLT Pq Ic getdlt
+This control message returns the current data link type of the
+.Va in
+and
+.Va out
+hooks.
.El
.Pp
In all redirection messages
@@ -336,11 +368,31 @@ serial line with HDLC encapsulation.
SEQ
ifconfig ng0 x.y.8.35 x.y.8.1
.Ed
+.Pp
+The
+.Nm
+node can also be attached directly to the physical interface
+via
+.Xr ng_ether 4
+node in the graph.
+In the following example, we perform masquerading on a
+Ethernet interface connected to a public network.
+.Bd -literal -offset indent
+ifconfig igb0 inet x.y.8.35 netmask 0xfffff000
+route add default x.y.0.1
+/usr/sbin/ngctl -f- <<-SEQ
+ mkpeer igb0: nat lower in
+ name igb0:lower igb0_NAT
+ connect igb0: igb0_NAT: upper out
+ msg igb0_NAT: setdlt 1
+ msg igb0_NAT: setaliasaddr x.y.8.35
+SEQ
.Sh SEE ALSO
.Xr libalias 3 ,
.Xr ng_ipfw 4 ,
.Xr natd 8 ,
-.Xr ngctl 8
+.Xr ngctl 8 ,
+.Xr ng_ether 8
.Sh HISTORY
The
.Nm
Modified: stable/11/sys/netgraph/ng_nat.c
==============================================================================
--- stable/11/sys/netgraph/ng_nat.c Tue Apr 7 16:44:14 2020 (r359697)
+++ stable/11/sys/netgraph/ng_nat.c Tue Apr 7 16:47:35 2020 (r359698)
@@ -42,6 +42,9 @@
#include <netinet/tcp.h>
#include <machine/in_cksum.h>
+#include <net/dlt.h>
+#include <net/ethernet.h>
+
#include <netinet/libalias/alias.h>
#include <netinet/libalias/alias_local.h>
@@ -239,6 +242,20 @@ static const struct ng_cmdlist ng_nat_cmdlist[] = {
NULL,
&ng_nat_libalias_info_type
},
+ {
+ NGM_NAT_COOKIE,
+ NGM_NAT_SET_DLT,
+ "setdlt",
+ &ng_parse_uint8_type,
+ NULL
+ },
+ {
+ NGM_NAT_COOKIE,
+ NGM_NAT_GET_DLT,
+ "getdlt",
+ NULL,
+ &ng_parse_uint8_type
+ },
{ 0 }
};
@@ -275,6 +292,7 @@ struct ng_nat_priv {
uint32_t rdrcount; /* number or redirects in list */
uint32_t nextid; /* for next in turn in list */
struct rdrhead redirhead; /* redirect list header */
+ uint8_t dlt; /* DLT_XXX from bpf.h */
};
typedef struct ng_nat_priv *priv_p;
@@ -300,6 +318,7 @@ ng_nat_constructor(node_p node)
/* Init redirects housekeeping. */
priv->rdrcount = 0;
priv->nextid = 1;
+ priv->dlt = DLT_RAW;
STAILQ_INIT(&priv->redirhead);
/* Link structs together. */
@@ -692,11 +711,34 @@ ng_nat_rcvmsg(node_p node, item_p item, hook_p lasthoo
#undef COPY
}
break;
+ case NGM_NAT_SET_DLT:
+ if (msg->header.arglen != sizeof(uint8_t)) {
+ error = EINVAL;
+ break;
+ }
+ switch (*(uint8_t *) msg->data) {
+ case DLT_EN10MB:
+ case DLT_RAW:
+ priv->dlt = *(uint8_t *) msg->data;
+ break;
+ default:
+ error = EINVAL;
+ break;
+ }
+ break;
default:
error = EINVAL; /* unknown command */
break;
}
break;
+ case NGM_NAT_GET_DLT:
+ NG_MKRESPONSE(resp, msg, sizeof(uint8_t), M_WAITOK);
+ if (resp == NULL) {
+ error = ENOMEM;
+ break;
+ }
+ *((uint8_t *) resp->data) = priv->dlt;
+ break;
default:
error = EINVAL; /* unknown cookie type */
break;
@@ -713,7 +755,7 @@ ng_nat_rcvdata(hook_p hook, item_p item )
const priv_p priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
struct mbuf *m;
struct ip *ip;
- int rval, error = 0;
+ int rval, ipofs, error = 0;
char *c;
/* We have no required hooks. */
@@ -736,12 +778,44 @@ ng_nat_rcvdata(hook_p hook, item_p item )
NGI_M(item) = m;
- c = mtod(m, char *);
- ip = mtod(m, struct ip *);
+ switch (priv->dlt) {
+ case DLT_RAW:
+ ipofs = 0;
+ break;
+ case DLT_EN10MB:
+ {
+ struct ether_header *eh;
- KASSERT(m->m_pkthdr.len == ntohs(ip->ip_len),
- ("ng_nat: ip_len != m_pkthdr.len"));
+ if (m->m_pkthdr.len < sizeof(struct ether_header)) {
+ NG_FREE_ITEM(item);
+ return (ENXIO);
+ }
+ eh = mtod(m, struct ether_header *);
+ switch (ntohs(eh->ether_type)) {
+ case ETHERTYPE_IP:
+ case ETHERTYPE_IPV6:
+ ipofs = sizeof(struct ether_header);
+ break;
+ default:
+ goto send;
+ }
+ break;
+ }
+ default:
+ panic("Corrupted priv->dlt: %u", priv->dlt);
+ }
+ if (m->m_pkthdr.len < ipofs + sizeof(struct ip))
+ goto send; /* packet too short to hold IP */
+
+ c = (char *)mtodo(m, ipofs);
+ ip = (struct ip *)mtodo(m, ipofs);
+
+ if (ip->ip_v != IPVERSION)
+ goto send; /* other IP version, let it pass */
+ if (m->m_pkthdr.len < ipofs + ntohs(ip->ip_len))
+ goto send; /* packet too short (i.e. fragmented or broken) */
+
/*
* We drop packet when:
* 1. libalias returns PKT_ALIAS_ERROR;
@@ -751,7 +825,8 @@ ng_nat_rcvdata(hook_p hook, item_p item )
* PKT_ALIAS_DENY_INCOMING flag is set.
*/
if (hook == priv->in) {
- rval = LibAliasIn(priv->lib, c, m->m_len + M_TRAILINGSPACE(m));
+ rval = LibAliasIn(priv->lib, c, m->m_len - ipofs +
+ M_TRAILINGSPACE(m));
if (rval == PKT_ALIAS_ERROR ||
rval == PKT_ALIAS_UNRESOLVED_FRAGMENT ||
(rval == PKT_ALIAS_IGNORED &&
@@ -761,7 +836,8 @@ ng_nat_rcvdata(hook_p hook, item_p item )
return (EINVAL);
}
} else if (hook == priv->out) {
- rval = LibAliasOut(priv->lib, c, m->m_len + M_TRAILINGSPACE(m));
+ rval = LibAliasOut(priv->lib, c, m->m_len - ipofs +
+ M_TRAILINGSPACE(m));
if (rval == PKT_ALIAS_ERROR) {
NG_FREE_ITEM(item);
return (EINVAL);
@@ -771,7 +847,7 @@ ng_nat_rcvdata(hook_p hook, item_p item )
if (rval == PKT_ALIAS_RESPOND)
m->m_flags |= M_SKIP_FIREWALL;
- m->m_pkthdr.len = m->m_len = ntohs(ip->ip_len);
+ m->m_pkthdr.len = m->m_len = ntohs(ip->ip_len) + ipofs;
if ((ip->ip_off & htons(IP_OFFMASK)) == 0 &&
ip->ip_p == IPPROTO_TCP) {
Modified: stable/11/sys/netgraph/ng_nat.h
==============================================================================
--- stable/11/sys/netgraph/ng_nat.h Tue Apr 7 16:44:14 2020 (r359697)
+++ stable/11/sys/netgraph/ng_nat.h Tue Apr 7 16:47:35 2020 (r359698)
@@ -203,6 +203,8 @@ enum {
NGM_NAT_SET_IPADDR = 1,
NGM_NAT_SET_MODE,
NGM_NAT_SET_TARGET,
+ NGM_NAT_SET_DLT,
+ NGM_NAT_GET_DLT,
NGM_NAT_REDIRECT_PORT,
NGM_NAT_REDIRECT_ADDR,
NGM_NAT_REDIRECT_PROTO,
More information about the svn-src-all
mailing list