Date: Mon, 17 Dec 2018 16:00:35 +0000 (UTC) From: Maxim Sobolev <sobomax@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r342168 - in head: share/man/man4 sys/netgraph Message-ID: <201812171600.wBHG0Zet046365@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: sobomax Date: Mon Dec 17 16:00:35 2018 New Revision: 342168 URL: https://svnweb.freebsd.org/changeset/base/342168 Log: 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). Approved by: glebius MFC after: 1 month Differential Revision: https://reviews.freebsd.org/D18535 Modified: head/share/man/man4/ng_nat.4 head/sys/netgraph/ng_nat.c head/sys/netgraph/ng_nat.h Modified: head/share/man/man4/ng_nat.4 ============================================================================== --- head/share/man/man4/ng_nat.4 Mon Dec 17 15:19:48 2018 (r342167) +++ head/share/man/man4/ng_nat.4 Mon Dec 17 16:00:35 2018 (r342168) @@ -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: head/sys/netgraph/ng_nat.c ============================================================================== --- head/sys/netgraph/ng_nat.c Mon Dec 17 15:19:48 2018 (r342167) +++ head/sys/netgraph/ng_nat.c Mon Dec 17 16:00:35 2018 (r342168) @@ -44,6 +44,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> @@ -241,6 +244,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 } }; @@ -277,6 +294,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; @@ -302,6 +320,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. */ @@ -694,11 +713,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; @@ -715,7 +757,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. */ @@ -738,10 +780,37 @@ 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), + 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); + } + + c = (char *)mtodo(m, ipofs); + ip = (struct ip *)mtodo(m, ipofs); + + KASSERT(m->m_pkthdr.len == ipofs + ntohs(ip->ip_len), ("ng_nat: ip_len != m_pkthdr.len")); /* @@ -753,7 +822,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 && @@ -763,7 +833,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); @@ -773,7 +844,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: head/sys/netgraph/ng_nat.h ============================================================================== --- head/sys/netgraph/ng_nat.h Mon Dec 17 15:19:48 2018 (r342167) +++ head/sys/netgraph/ng_nat.h Mon Dec 17 16:00:35 2018 (r342168) @@ -205,6 +205,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,
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201812171600.wBHG0Zet046365>