ng_nat.c (fe267a559009cbf34f9341666fe4d88a92c02d5e) ng_nat.c (b7841ae6501e2cbb0a3d90ea412f2591d4b17f55)
1/*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright 2005, Gleb Smirnoff <glebius@FreeBSD.org>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions

--- 30 unchanged lines hidden (view full) ---

39
40#include <netinet/in_systm.h>
41#include <netinet/in.h>
42#include <netinet/ip.h>
43#include <netinet/ip_var.h>
44#include <netinet/tcp.h>
45#include <machine/in_cksum.h>
46
1/*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright 2005, Gleb Smirnoff <glebius@FreeBSD.org>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions

--- 30 unchanged lines hidden (view full) ---

39
40#include <netinet/in_systm.h>
41#include <netinet/in.h>
42#include <netinet/ip.h>
43#include <netinet/ip_var.h>
44#include <netinet/tcp.h>
45#include <machine/in_cksum.h>
46
47#include <net/dlt.h>
48#include <net/ethernet.h>
49
47#include <netinet/libalias/alias.h>
48#include <netinet/libalias/alias_local.h>
49
50#include <netgraph/ng_message.h>
51#include <netgraph/ng_parse.h>
52#include <netgraph/ng_nat.h>
53#include <netgraph/netgraph.h>
54

--- 181 unchanged lines hidden (view full) ---

236 },
237 {
238 NGM_NAT_COOKIE,
239 NGM_NAT_LIBALIAS_INFO,
240 "libaliasinfo",
241 NULL,
242 &ng_nat_libalias_info_type
243 },
50#include <netinet/libalias/alias.h>
51#include <netinet/libalias/alias_local.h>
52
53#include <netgraph/ng_message.h>
54#include <netgraph/ng_parse.h>
55#include <netgraph/ng_nat.h>
56#include <netgraph/netgraph.h>
57

--- 181 unchanged lines hidden (view full) ---

239 },
240 {
241 NGM_NAT_COOKIE,
242 NGM_NAT_LIBALIAS_INFO,
243 "libaliasinfo",
244 NULL,
245 &ng_nat_libalias_info_type
246 },
247 {
248 NGM_NAT_COOKIE,
249 NGM_NAT_SET_DLT,
250 "setdlt",
251 &ng_parse_uint8_type,
252 NULL
253 },
254 {
255 NGM_NAT_COOKIE,
256 NGM_NAT_GET_DLT,
257 "getdlt",
258 NULL,
259 &ng_parse_uint8_type
260 },
244 { 0 }
245};
246
247/* Netgraph node type descriptor. */
248static struct ng_type typestruct = {
249 .version = NG_ABI_VERSION,
250 .name = NG_NAT_NODE_TYPE,
251 .constructor = ng_nat_constructor,

--- 20 unchanged lines hidden (view full) ---

272 node_p node; /* back pointer to node */
273 hook_p in; /* hook for demasquerading */
274 hook_p out; /* hook for masquerading */
275 struct libalias *lib; /* libalias handler */
276 uint32_t flags; /* status flags */
277 uint32_t rdrcount; /* number or redirects in list */
278 uint32_t nextid; /* for next in turn in list */
279 struct rdrhead redirhead; /* redirect list header */
261 { 0 }
262};
263
264/* Netgraph node type descriptor. */
265static struct ng_type typestruct = {
266 .version = NG_ABI_VERSION,
267 .name = NG_NAT_NODE_TYPE,
268 .constructor = ng_nat_constructor,

--- 20 unchanged lines hidden (view full) ---

289 node_p node; /* back pointer to node */
290 hook_p in; /* hook for demasquerading */
291 hook_p out; /* hook for masquerading */
292 struct libalias *lib; /* libalias handler */
293 uint32_t flags; /* status flags */
294 uint32_t rdrcount; /* number or redirects in list */
295 uint32_t nextid; /* for next in turn in list */
296 struct rdrhead redirhead; /* redirect list header */
297 uint8_t dlt; /* DLT_XXX from bpf.h */
280};
281typedef struct ng_nat_priv *priv_p;
282
283/* Values of flags */
284#define NGNAT_CONNECTED 0x1 /* We have both hooks connected */
285#define NGNAT_ADDR_DEFINED 0x2 /* NGM_NAT_SET_IPADDR happened */
286
287static int

--- 9 unchanged lines hidden (view full) ---

297
298 /* Set same ports on. */
299 (void )LibAliasSetMode(priv->lib, PKT_ALIAS_SAME_PORTS,
300 PKT_ALIAS_SAME_PORTS);
301
302 /* Init redirects housekeeping. */
303 priv->rdrcount = 0;
304 priv->nextid = 1;
298};
299typedef struct ng_nat_priv *priv_p;
300
301/* Values of flags */
302#define NGNAT_CONNECTED 0x1 /* We have both hooks connected */
303#define NGNAT_ADDR_DEFINED 0x2 /* NGM_NAT_SET_IPADDR happened */
304
305static int

--- 9 unchanged lines hidden (view full) ---

315
316 /* Set same ports on. */
317 (void )LibAliasSetMode(priv->lib, PKT_ALIAS_SAME_PORTS,
318 PKT_ALIAS_SAME_PORTS);
319
320 /* Init redirects housekeeping. */
321 priv->rdrcount = 0;
322 priv->nextid = 1;
323 priv->dlt = DLT_RAW;
305 STAILQ_INIT(&priv->redirhead);
306
307 /* Link structs together. */
308 NG_NODE_SET_PRIVATE(node, priv);
309 priv->node = node;
310
311 /*
312 * libalias is not thread safe, so our node

--- 376 unchanged lines hidden (view full) ---

689 COPY(sctpLinkCount);
690 COPY(protoLinkCount);
691 COPY(fragmentIdLinkCount);
692 COPY(fragmentPtrLinkCount);
693 COPY(sockCount);
694#undef COPY
695 }
696 break;
324 STAILQ_INIT(&priv->redirhead);
325
326 /* Link structs together. */
327 NG_NODE_SET_PRIVATE(node, priv);
328 priv->node = node;
329
330 /*
331 * libalias is not thread safe, so our node

--- 376 unchanged lines hidden (view full) ---

708 COPY(sctpLinkCount);
709 COPY(protoLinkCount);
710 COPY(fragmentIdLinkCount);
711 COPY(fragmentPtrLinkCount);
712 COPY(sockCount);
713#undef COPY
714 }
715 break;
716 case NGM_NAT_SET_DLT:
717 if (msg->header.arglen != sizeof(uint8_t)) {
718 error = EINVAL;
719 break;
720 }
721 switch (*(uint8_t *) msg->data) {
722 case DLT_EN10MB:
723 case DLT_RAW:
724 priv->dlt = *(uint8_t *) msg->data;
725 break;
726 default:
727 error = EINVAL;
728 break;
729 }
730 break;
697 default:
698 error = EINVAL; /* unknown command */
699 break;
700 }
701 break;
731 default:
732 error = EINVAL; /* unknown command */
733 break;
734 }
735 break;
736 case NGM_NAT_GET_DLT:
737 NG_MKRESPONSE(resp, msg, sizeof(uint8_t), M_WAITOK);
738 if (resp == NULL) {
739 error = ENOMEM;
740 break;
741 }
742 *((uint8_t *) resp->data) = priv->dlt;
743 break;
702 default:
703 error = EINVAL; /* unknown cookie type */
704 break;
705 }
706
707 NG_RESPOND_MSG(error, node, item, resp);
708 NG_FREE_MSG(msg);
709 return (error);
710}
711
712static int
713ng_nat_rcvdata(hook_p hook, item_p item )
714{
715 const priv_p priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
716 struct mbuf *m;
717 struct ip *ip;
744 default:
745 error = EINVAL; /* unknown cookie type */
746 break;
747 }
748
749 NG_RESPOND_MSG(error, node, item, resp);
750 NG_FREE_MSG(msg);
751 return (error);
752}
753
754static int
755ng_nat_rcvdata(hook_p hook, item_p item )
756{
757 const priv_p priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
758 struct mbuf *m;
759 struct ip *ip;
718 int rval, error = 0;
760 int rval, ipofs, error = 0;
719 char *c;
720
721 /* We have no required hooks. */
722 if (!(priv->flags & NGNAT_CONNECTED)) {
723 NG_FREE_ITEM(item);
724 return (ENXIO);
725 }
726

--- 6 unchanged lines hidden (view full) ---

733 if ((m = m_megapullup(m, m->m_pkthdr.len)) == NULL) {
734 NGI_M(item) = NULL; /* avoid double free */
735 NG_FREE_ITEM(item);
736 return (ENOBUFS);
737 }
738
739 NGI_M(item) = m;
740
761 char *c;
762
763 /* We have no required hooks. */
764 if (!(priv->flags & NGNAT_CONNECTED)) {
765 NG_FREE_ITEM(item);
766 return (ENXIO);
767 }
768

--- 6 unchanged lines hidden (view full) ---

775 if ((m = m_megapullup(m, m->m_pkthdr.len)) == NULL) {
776 NGI_M(item) = NULL; /* avoid double free */
777 NG_FREE_ITEM(item);
778 return (ENOBUFS);
779 }
780
781 NGI_M(item) = m;
782
741 c = mtod(m, char *);
742 ip = mtod(m, struct ip *);
783 switch (priv->dlt) {
784 case DLT_RAW:
785 ipofs = 0;
786 break;
787 case DLT_EN10MB:
788 {
789 struct ether_header *eh;
743
790
744 KASSERT(m->m_pkthdr.len == ntohs(ip->ip_len),
791 if (m->m_pkthdr.len < sizeof(struct ether_header)) {
792 NG_FREE_ITEM(item);
793 return (ENXIO);
794 }
795 eh = mtod(m, struct ether_header *);
796 switch (ntohs(eh->ether_type)) {
797 case ETHERTYPE_IP:
798 case ETHERTYPE_IPV6:
799 ipofs = sizeof(struct ether_header);
800 break;
801 default:
802 goto send;
803 }
804 break;
805 }
806 default:
807 panic("Corrupted priv->dlt: %u", priv->dlt);
808 }
809
810 c = (char *)mtodo(m, ipofs);
811 ip = (struct ip *)mtodo(m, ipofs);
812
813 KASSERT(m->m_pkthdr.len == ipofs + ntohs(ip->ip_len),
745 ("ng_nat: ip_len != m_pkthdr.len"));
746
747 /*
748 * We drop packet when:
749 * 1. libalias returns PKT_ALIAS_ERROR;
750 * 2. For incoming packets:
751 * a) for unresolved fragments;
752 * b) libalias returns PKT_ALIAS_IGNORED and
753 * PKT_ALIAS_DENY_INCOMING flag is set.
754 */
755 if (hook == priv->in) {
814 ("ng_nat: ip_len != m_pkthdr.len"));
815
816 /*
817 * We drop packet when:
818 * 1. libalias returns PKT_ALIAS_ERROR;
819 * 2. For incoming packets:
820 * a) for unresolved fragments;
821 * b) libalias returns PKT_ALIAS_IGNORED and
822 * PKT_ALIAS_DENY_INCOMING flag is set.
823 */
824 if (hook == priv->in) {
756 rval = LibAliasIn(priv->lib, c, m->m_len + M_TRAILINGSPACE(m));
825 rval = LibAliasIn(priv->lib, c, m->m_len - ipofs +
826 M_TRAILINGSPACE(m));
757 if (rval == PKT_ALIAS_ERROR ||
758 rval == PKT_ALIAS_UNRESOLVED_FRAGMENT ||
759 (rval == PKT_ALIAS_IGNORED &&
760 (priv->lib->packetAliasMode &
761 PKT_ALIAS_DENY_INCOMING) != 0)) {
762 NG_FREE_ITEM(item);
763 return (EINVAL);
764 }
765 } else if (hook == priv->out) {
827 if (rval == PKT_ALIAS_ERROR ||
828 rval == PKT_ALIAS_UNRESOLVED_FRAGMENT ||
829 (rval == PKT_ALIAS_IGNORED &&
830 (priv->lib->packetAliasMode &
831 PKT_ALIAS_DENY_INCOMING) != 0)) {
832 NG_FREE_ITEM(item);
833 return (EINVAL);
834 }
835 } else if (hook == priv->out) {
766 rval = LibAliasOut(priv->lib, c, m->m_len + M_TRAILINGSPACE(m));
836 rval = LibAliasOut(priv->lib, c, m->m_len - ipofs +
837 M_TRAILINGSPACE(m));
767 if (rval == PKT_ALIAS_ERROR) {
768 NG_FREE_ITEM(item);
769 return (EINVAL);
770 }
771 } else
772 panic("ng_nat: unknown hook!\n");
773
774 if (rval == PKT_ALIAS_RESPOND)
775 m->m_flags |= M_SKIP_FIREWALL;
838 if (rval == PKT_ALIAS_ERROR) {
839 NG_FREE_ITEM(item);
840 return (EINVAL);
841 }
842 } else
843 panic("ng_nat: unknown hook!\n");
844
845 if (rval == PKT_ALIAS_RESPOND)
846 m->m_flags |= M_SKIP_FIREWALL;
776 m->m_pkthdr.len = m->m_len = ntohs(ip->ip_len);
847 m->m_pkthdr.len = m->m_len = ntohs(ip->ip_len) + ipofs;
777
778 if ((ip->ip_off & htons(IP_OFFMASK)) == 0 &&
779 ip->ip_p == IPPROTO_TCP) {
780 struct tcphdr *th = (struct tcphdr *)((caddr_t)ip +
781 (ip->ip_hl << 2));
782
783 /*
784 * Here is our terrible HACK.

--- 107 unchanged lines hidden ---
848
849 if ((ip->ip_off & htons(IP_OFFMASK)) == 0 &&
850 ip->ip_p == IPPROTO_TCP) {
851 struct tcphdr *th = (struct tcphdr *)((caddr_t)ip +
852 (ip->ip_hl << 2));
853
854 /*
855 * Here is our terrible HACK.

--- 107 unchanged lines hidden ---