2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 * Copyright 2005, Gleb Smirnoff <glebius@FreeBSD.org>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 #include <sys/param.h>
32 #include <sys/systm.h>
33 #include <sys/kernel.h>
35 #include <sys/malloc.h>
36 #include <sys/ctype.h>
37 #include <sys/errno.h>
38 #include <sys/syslog.h>
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>
48 #include <net/ethernet.h>
50 #include <netinet/libalias/alias.h>
51 #include <netinet/libalias/alias_local.h>
53 #include <netgraph/ng_message.h>
54 #include <netgraph/ng_parse.h>
55 #include <netgraph/ng_nat.h>
56 #include <netgraph/netgraph.h>
58 static ng_constructor_t ng_nat_constructor;
59 static ng_rcvmsg_t ng_nat_rcvmsg;
60 static ng_shutdown_t ng_nat_shutdown;
61 static ng_newhook_t ng_nat_newhook;
62 static ng_rcvdata_t ng_nat_rcvdata;
63 static ng_disconnect_t ng_nat_disconnect;
65 static unsigned int ng_nat_translate_flags(unsigned int x);
67 /* Parse type for struct ng_nat_mode. */
68 static const struct ng_parse_struct_field ng_nat_mode_fields[]
70 static const struct ng_parse_type ng_nat_mode_type = {
71 &ng_parse_struct_type,
75 /* Parse type for 'description' field in structs. */
76 static const struct ng_parse_fixedstring_info ng_nat_description_info
77 = { NG_NAT_DESC_LENGTH };
78 static const struct ng_parse_type ng_nat_description_type = {
79 &ng_parse_fixedstring_type,
80 &ng_nat_description_info
83 /* Parse type for struct ng_nat_redirect_port. */
84 static const struct ng_parse_struct_field ng_nat_redirect_port_fields[]
85 = NG_NAT_REDIRECT_PORT_TYPE_INFO(&ng_nat_description_type);
86 static const struct ng_parse_type ng_nat_redirect_port_type = {
87 &ng_parse_struct_type,
88 &ng_nat_redirect_port_fields
91 /* Parse type for struct ng_nat_redirect_addr. */
92 static const struct ng_parse_struct_field ng_nat_redirect_addr_fields[]
93 = NG_NAT_REDIRECT_ADDR_TYPE_INFO(&ng_nat_description_type);
94 static const struct ng_parse_type ng_nat_redirect_addr_type = {
95 &ng_parse_struct_type,
96 &ng_nat_redirect_addr_fields
99 /* Parse type for struct ng_nat_redirect_proto. */
100 static const struct ng_parse_struct_field ng_nat_redirect_proto_fields[]
101 = NG_NAT_REDIRECT_PROTO_TYPE_INFO(&ng_nat_description_type);
102 static const struct ng_parse_type ng_nat_redirect_proto_type = {
103 &ng_parse_struct_type,
104 &ng_nat_redirect_proto_fields
107 /* Parse type for struct ng_nat_add_server. */
108 static const struct ng_parse_struct_field ng_nat_add_server_fields[]
109 = NG_NAT_ADD_SERVER_TYPE_INFO;
110 static const struct ng_parse_type ng_nat_add_server_type = {
111 &ng_parse_struct_type,
112 &ng_nat_add_server_fields
115 /* Parse type for one struct ng_nat_listrdrs_entry. */
116 static const struct ng_parse_struct_field ng_nat_listrdrs_entry_fields[]
117 = NG_NAT_LISTRDRS_ENTRY_TYPE_INFO(&ng_nat_description_type);
118 static const struct ng_parse_type ng_nat_listrdrs_entry_type = {
119 &ng_parse_struct_type,
120 &ng_nat_listrdrs_entry_fields
123 /* Parse type for 'redirects' array in struct ng_nat_list_redirects. */
125 ng_nat_listrdrs_ary_getLength(const struct ng_parse_type *type,
126 const u_char *start, const u_char *buf)
128 const struct ng_nat_list_redirects *lr;
130 lr = (const struct ng_nat_list_redirects *)
131 (buf - offsetof(struct ng_nat_list_redirects, redirects));
132 return lr->total_count;
135 static const struct ng_parse_array_info ng_nat_listrdrs_ary_info = {
136 &ng_nat_listrdrs_entry_type,
137 &ng_nat_listrdrs_ary_getLength,
140 static const struct ng_parse_type ng_nat_listrdrs_ary_type = {
141 &ng_parse_array_type,
142 &ng_nat_listrdrs_ary_info
145 /* Parse type for struct ng_nat_list_redirects. */
146 static const struct ng_parse_struct_field ng_nat_list_redirects_fields[]
147 = NG_NAT_LIST_REDIRECTS_TYPE_INFO(&ng_nat_listrdrs_ary_type);
148 static const struct ng_parse_type ng_nat_list_redirects_type = {
149 &ng_parse_struct_type,
150 &ng_nat_list_redirects_fields
153 /* Parse type for struct ng_nat_libalias_info. */
154 static const struct ng_parse_struct_field ng_nat_libalias_info_fields[]
155 = NG_NAT_LIBALIAS_INFO;
156 static const struct ng_parse_type ng_nat_libalias_info_type = {
157 &ng_parse_struct_type,
158 &ng_nat_libalias_info_fields
161 /* List of commands and how to convert arguments to/from ASCII. */
162 static const struct ng_cmdlist ng_nat_cmdlist[] = {
167 &ng_parse_ipaddr_type,
181 &ng_parse_ipaddr_type,
186 NGM_NAT_REDIRECT_PORT,
188 &ng_nat_redirect_port_type,
189 &ng_parse_uint32_type
193 NGM_NAT_REDIRECT_ADDR,
195 &ng_nat_redirect_addr_type,
196 &ng_parse_uint32_type
200 NGM_NAT_REDIRECT_PROTO,
202 &ng_nat_redirect_proto_type,
203 &ng_parse_uint32_type
207 NGM_NAT_REDIRECT_DYNAMIC,
209 &ng_parse_uint32_type,
214 NGM_NAT_REDIRECT_DELETE,
216 &ng_parse_uint32_type,
223 &ng_nat_add_server_type,
228 NGM_NAT_LIST_REDIRECTS,
231 &ng_nat_list_redirects_type
237 &ng_parse_string_type,
242 NGM_NAT_LIBALIAS_INFO,
245 &ng_nat_libalias_info_type
251 &ng_parse_uint8_type,
264 /* Netgraph node type descriptor. */
265 static struct ng_type typestruct = {
266 .version = NG_ABI_VERSION,
267 .name = NG_NAT_NODE_TYPE,
268 .constructor = ng_nat_constructor,
269 .rcvmsg = ng_nat_rcvmsg,
270 .shutdown = ng_nat_shutdown,
271 .newhook = ng_nat_newhook,
272 .rcvdata = ng_nat_rcvdata,
273 .disconnect = ng_nat_disconnect,
274 .cmdlist = ng_nat_cmdlist,
276 NETGRAPH_INIT(nat, &typestruct);
277 MODULE_DEPEND(ng_nat, libalias, 1, 1, 1);
279 /* Element for list of redirects. */
280 struct ng_nat_rdr_lst {
281 STAILQ_ENTRY(ng_nat_rdr_lst) entries;
282 struct alias_link *lnk;
283 struct ng_nat_listrdrs_entry rdr;
285 STAILQ_HEAD(rdrhead, ng_nat_rdr_lst);
287 /* Information we store for each node. */
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 */
299 typedef struct ng_nat_priv *priv_p;
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 */
306 ng_nat_constructor(node_p node)
310 /* Initialize private descriptor. */
311 priv = malloc(sizeof(*priv), M_NETGRAPH, M_WAITOK | M_ZERO);
313 /* Init aliasing engine. */
314 priv->lib = LibAliasInit(NULL);
316 /* Set same ports on. */
317 (void )LibAliasSetMode(priv->lib, PKT_ALIAS_SAME_PORTS,
318 PKT_ALIAS_SAME_PORTS);
320 /* Init redirects housekeeping. */
324 STAILQ_INIT(&priv->redirhead);
326 /* Link structs together. */
327 NG_NODE_SET_PRIVATE(node, priv);
331 * libalias is not thread safe, so our node
332 * must be single threaded.
334 NG_NODE_FORCE_WRITER(node);
340 ng_nat_newhook(node_p node, hook_p hook, const char *name)
342 const priv_p priv = NG_NODE_PRIVATE(node);
344 if (strcmp(name, NG_NAT_HOOK_IN) == 0) {
346 } else if (strcmp(name, NG_NAT_HOOK_OUT) == 0) {
351 if (priv->out != NULL &&
353 priv->flags |= NGNAT_CONNECTED;
359 ng_nat_rcvmsg(node_p node, item_p item, hook_p lasthook)
361 const priv_p priv = NG_NODE_PRIVATE(node);
362 struct ng_mesg *resp = NULL;
366 NGI_GET_MSG(item, msg);
368 switch (msg->header.typecookie) {
370 switch (msg->header.cmd) {
371 case NGM_NAT_SET_IPADDR:
373 struct in_addr *const ia = (struct in_addr *)msg->data;
375 if (msg->header.arglen < sizeof(*ia)) {
380 LibAliasSetAddress(priv->lib, *ia);
382 priv->flags |= NGNAT_ADDR_DEFINED;
385 case NGM_NAT_SET_MODE:
387 struct ng_nat_mode *const mode =
388 (struct ng_nat_mode *)msg->data;
390 if (msg->header.arglen < sizeof(*mode)) {
395 if (LibAliasSetMode(priv->lib,
396 ng_nat_translate_flags(mode->flags),
397 ng_nat_translate_flags(mode->mask)) < 0) {
403 case NGM_NAT_SET_TARGET:
405 struct in_addr *const ia = (struct in_addr *)msg->data;
407 if (msg->header.arglen < sizeof(*ia)) {
412 LibAliasSetTarget(priv->lib, *ia);
415 case NGM_NAT_REDIRECT_PORT:
417 struct ng_nat_rdr_lst *entry;
418 struct ng_nat_redirect_port *const rp =
419 (struct ng_nat_redirect_port *)msg->data;
421 if (msg->header.arglen < sizeof(*rp)) {
426 if ((entry = malloc(sizeof(struct ng_nat_rdr_lst),
427 M_NETGRAPH, M_NOWAIT | M_ZERO)) == NULL) {
432 /* Try actual redirect. */
433 entry->lnk = LibAliasRedirectPort(priv->lib,
434 rp->local_addr, htons(rp->local_port),
435 rp->remote_addr, htons(rp->remote_port),
436 rp->alias_addr, htons(rp->alias_port),
439 if (entry->lnk == NULL) {
441 free(entry, M_NETGRAPH);
445 /* Successful, save info in our internal list. */
446 entry->rdr.local_addr = rp->local_addr;
447 entry->rdr.alias_addr = rp->alias_addr;
448 entry->rdr.remote_addr = rp->remote_addr;
449 entry->rdr.local_port = rp->local_port;
450 entry->rdr.alias_port = rp->alias_port;
451 entry->rdr.remote_port = rp->remote_port;
452 entry->rdr.proto = rp->proto;
453 bcopy(rp->description, entry->rdr.description,
456 /* Safety precaution. */
457 entry->rdr.description[NG_NAT_DESC_LENGTH-1] = '\0';
459 entry->rdr.id = priv->nextid++;
462 /* Link to list of redirects. */
463 STAILQ_INSERT_TAIL(&priv->redirhead, entry, entries);
465 /* Response with id of newly added entry. */
466 NG_MKRESPONSE(resp, msg, sizeof(entry->rdr.id), M_NOWAIT);
471 bcopy(&entry->rdr.id, resp->data, sizeof(entry->rdr.id));
474 case NGM_NAT_REDIRECT_ADDR:
476 struct ng_nat_rdr_lst *entry;
477 struct ng_nat_redirect_addr *const ra =
478 (struct ng_nat_redirect_addr *)msg->data;
480 if (msg->header.arglen < sizeof(*ra)) {
485 if ((entry = malloc(sizeof(struct ng_nat_rdr_lst),
486 M_NETGRAPH, M_NOWAIT | M_ZERO)) == NULL) {
491 /* Try actual redirect. */
492 entry->lnk = LibAliasRedirectAddr(priv->lib,
493 ra->local_addr, ra->alias_addr);
495 if (entry->lnk == NULL) {
497 free(entry, M_NETGRAPH);
501 /* Successful, save info in our internal list. */
502 entry->rdr.local_addr = ra->local_addr;
503 entry->rdr.alias_addr = ra->alias_addr;
504 entry->rdr.proto = NG_NAT_REDIRPROTO_ADDR;
505 bcopy(ra->description, entry->rdr.description,
508 /* Safety precaution. */
509 entry->rdr.description[NG_NAT_DESC_LENGTH-1] = '\0';
511 entry->rdr.id = priv->nextid++;
514 /* Link to list of redirects. */
515 STAILQ_INSERT_TAIL(&priv->redirhead, entry, entries);
517 /* Response with id of newly added entry. */
518 NG_MKRESPONSE(resp, msg, sizeof(entry->rdr.id), M_NOWAIT);
523 bcopy(&entry->rdr.id, resp->data, sizeof(entry->rdr.id));
526 case NGM_NAT_REDIRECT_PROTO:
528 struct ng_nat_rdr_lst *entry;
529 struct ng_nat_redirect_proto *const rp =
530 (struct ng_nat_redirect_proto *)msg->data;
532 if (msg->header.arglen < sizeof(*rp)) {
537 if ((entry = malloc(sizeof(struct ng_nat_rdr_lst),
538 M_NETGRAPH, M_NOWAIT | M_ZERO)) == NULL) {
543 /* Try actual redirect. */
544 entry->lnk = LibAliasRedirectProto(priv->lib,
545 rp->local_addr, rp->remote_addr,
546 rp->alias_addr, rp->proto);
548 if (entry->lnk == NULL) {
550 free(entry, M_NETGRAPH);
554 /* Successful, save info in our internal list. */
555 entry->rdr.local_addr = rp->local_addr;
556 entry->rdr.alias_addr = rp->alias_addr;
557 entry->rdr.remote_addr = rp->remote_addr;
558 entry->rdr.proto = rp->proto;
559 bcopy(rp->description, entry->rdr.description,
562 /* Safety precaution. */
563 entry->rdr.description[NG_NAT_DESC_LENGTH-1] = '\0';
565 entry->rdr.id = priv->nextid++;
568 /* Link to list of redirects. */
569 STAILQ_INSERT_TAIL(&priv->redirhead, entry, entries);
571 /* Response with id of newly added entry. */
572 NG_MKRESPONSE(resp, msg, sizeof(entry->rdr.id), M_NOWAIT);
577 bcopy(&entry->rdr.id, resp->data, sizeof(entry->rdr.id));
580 case NGM_NAT_REDIRECT_DYNAMIC:
581 case NGM_NAT_REDIRECT_DELETE:
583 struct ng_nat_rdr_lst *entry;
584 uint32_t *const id = (uint32_t *)msg->data;
586 if (msg->header.arglen < sizeof(*id)) {
591 /* Find entry with supplied id. */
592 STAILQ_FOREACH(entry, &priv->redirhead, entries) {
593 if (entry->rdr.id == *id)
603 if (msg->header.cmd == NGM_NAT_REDIRECT_DYNAMIC) {
604 if (LibAliasRedirectDynamic(priv->lib,
606 error = ENOTTY; /* XXX Something better? */
609 } else { /* NGM_NAT_REDIRECT_DELETE */
610 LibAliasRedirectDelete(priv->lib, entry->lnk);
613 /* Delete entry from our internal list. */
615 STAILQ_REMOVE(&priv->redirhead, entry, ng_nat_rdr_lst, entries);
616 free(entry, M_NETGRAPH);
619 case NGM_NAT_ADD_SERVER:
621 struct ng_nat_rdr_lst *entry;
622 struct ng_nat_add_server *const as =
623 (struct ng_nat_add_server *)msg->data;
625 if (msg->header.arglen < sizeof(*as)) {
630 /* Find entry with supplied id. */
631 STAILQ_FOREACH(entry, &priv->redirhead, entries) {
632 if (entry->rdr.id == as->id)
642 if (LibAliasAddServer(priv->lib, entry->lnk,
643 as->addr, htons(as->port)) == -1) {
651 case NGM_NAT_LIST_REDIRECTS:
653 struct ng_nat_rdr_lst *entry;
654 struct ng_nat_list_redirects *ary;
657 NG_MKRESPONSE(resp, msg, sizeof(*ary) +
658 (priv->rdrcount) * sizeof(*entry), M_NOWAIT);
664 ary = (struct ng_nat_list_redirects *)resp->data;
665 ary->total_count = priv->rdrcount;
667 STAILQ_FOREACH(entry, &priv->redirhead, entries) {
668 bcopy(&entry->rdr, &ary->redirects[i++],
669 sizeof(struct ng_nat_listrdrs_entry));
673 case NGM_NAT_PROXY_RULE:
675 char *cmd = (char *)msg->data;
677 if (msg->header.arglen < 6) {
682 if (LibAliasProxyRule(priv->lib, cmd) != 0)
686 case NGM_NAT_LIBALIAS_INFO:
688 struct ng_nat_libalias_info *i;
690 NG_MKRESPONSE(resp, msg,
691 sizeof(struct ng_nat_libalias_info), M_NOWAIT);
696 i = (struct ng_nat_libalias_info *)resp->data;
697 #define COPY(F) do { \
698 if (priv->lib->F >= 0 && priv->lib->F < UINT32_MAX) \
699 i->F = priv->lib->F; \
709 COPY(protoLinkCount);
710 COPY(fragmentIdLinkCount);
711 COPY(fragmentPtrLinkCount);
716 case NGM_NAT_SET_DLT:
717 if (msg->header.arglen != sizeof(uint8_t)) {
721 switch (*(uint8_t *) msg->data) {
724 priv->dlt = *(uint8_t *) msg->data;
732 error = EINVAL; /* unknown command */
736 case NGM_NAT_GET_DLT:
737 NG_MKRESPONSE(resp, msg, sizeof(uint8_t), M_WAITOK);
742 *((uint8_t *) resp->data) = priv->dlt;
745 error = EINVAL; /* unknown cookie type */
749 NG_RESPOND_MSG(error, node, item, resp);
755 ng_nat_rcvdata(hook_p hook, item_p item )
757 const priv_p priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
760 int rval, ipofs, error = 0;
763 /* We have no required hooks. */
764 if (!(priv->flags & NGNAT_CONNECTED)) {
769 /* We have no alias address yet to do anything. */
770 if (!(priv->flags & NGNAT_ADDR_DEFINED))
775 if ((m = m_megapullup(m, m->m_pkthdr.len)) == NULL) {
776 NGI_M(item) = NULL; /* avoid double free */
789 struct ether_header *eh;
791 if (m->m_pkthdr.len < sizeof(struct ether_header)) {
795 eh = mtod(m, struct ether_header *);
796 switch (ntohs(eh->ether_type)) {
798 ipofs = sizeof(struct ether_header);
806 panic("Corrupted priv->dlt: %u", priv->dlt);
809 if (m->m_pkthdr.len < ipofs + sizeof(struct ip))
810 goto send; /* packet too short to hold IP */
812 c = (char *)mtodo(m, ipofs);
813 ip = (struct ip *)mtodo(m, ipofs);
815 if (ip->ip_v != IPVERSION)
816 goto send; /* other IP version, let it pass */
817 if (m->m_pkthdr.len < ipofs + ntohs(ip->ip_len))
818 goto send; /* packet too short (i.e. fragmented or broken) */
821 * We drop packet when:
822 * 1. libalias returns PKT_ALIAS_ERROR;
823 * 2. For incoming packets:
824 * a) for unresolved fragments;
825 * b) libalias returns PKT_ALIAS_IGNORED and
826 * PKT_ALIAS_DENY_INCOMING flag is set.
828 if (hook == priv->in) {
829 rval = LibAliasIn(priv->lib, c, m->m_len - ipofs +
831 if (rval == PKT_ALIAS_ERROR ||
832 rval == PKT_ALIAS_UNRESOLVED_FRAGMENT ||
833 (rval == PKT_ALIAS_IGNORED &&
834 (priv->lib->packetAliasMode &
835 PKT_ALIAS_DENY_INCOMING) != 0)) {
839 } else if (hook == priv->out) {
840 rval = LibAliasOut(priv->lib, c, m->m_len - ipofs +
842 if (rval == PKT_ALIAS_ERROR) {
847 panic("ng_nat: unknown hook!\n");
849 if (rval == PKT_ALIAS_RESPOND)
850 m->m_flags |= M_SKIP_FIREWALL;
851 m->m_pkthdr.len = m->m_len = ntohs(ip->ip_len) + ipofs;
853 if ((ip->ip_off & htons(IP_OFFMASK)) == 0 &&
854 ip->ip_p == IPPROTO_TCP) {
855 struct tcphdr *th = (struct tcphdr *)((caddr_t)ip +
859 * Here is our terrible HACK.
861 * Sometimes LibAlias edits contents of TCP packet.
862 * In this case it needs to recompute full TCP
863 * checksum. However, the problem is that LibAlias
864 * doesn't have any idea about checksum offloading
865 * in kernel. To workaround this, we do not do
866 * checksumming in LibAlias, but only mark the
867 * packets in th_x2 field. If we receive a marked
868 * packet, we calculate correct checksum for it
869 * aware of offloading.
871 * Why do I do such a terrible hack instead of
872 * recalculating checksum for each packet?
873 * Because the previous checksum was not checked!
874 * Recalculating checksums for EVERY packet will
875 * hide ALL transmission errors. Yes, marked packets
876 * still suffer from this problem. But, sigh, natd(8)
877 * has this problem, too.
881 uint16_t ip_len = ntohs(ip->ip_len);
884 th->th_sum = in_pseudo(ip->ip_src.s_addr,
885 ip->ip_dst.s_addr, htons(IPPROTO_TCP +
886 ip_len - (ip->ip_hl << 2)));
888 if ((m->m_pkthdr.csum_flags & CSUM_TCP) == 0) {
889 m->m_pkthdr.csum_data = offsetof(struct tcphdr,
897 if (hook == priv->in)
898 NG_FWD_ITEM_HOOK(error, item, priv->out);
900 NG_FWD_ITEM_HOOK(error, item, priv->in);
906 ng_nat_shutdown(node_p node)
908 const priv_p priv = NG_NODE_PRIVATE(node);
910 NG_NODE_SET_PRIVATE(node, NULL);
913 /* Free redirects list. */
914 while (!STAILQ_EMPTY(&priv->redirhead)) {
915 struct ng_nat_rdr_lst *entry = STAILQ_FIRST(&priv->redirhead);
916 STAILQ_REMOVE_HEAD(&priv->redirhead, entries);
917 free(entry, M_NETGRAPH);
921 LibAliasUninit(priv->lib);
922 free(priv, M_NETGRAPH);
928 ng_nat_disconnect(hook_p hook)
930 const priv_p priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
932 priv->flags &= ~NGNAT_CONNECTED;
934 if (hook == priv->out)
936 if (hook == priv->in)
939 if (priv->out == NULL && priv->in == NULL)
940 ng_rmnode_self(NG_HOOK_NODE(hook));
946 ng_nat_translate_flags(unsigned int x)
948 unsigned int res = 0;
951 res |= PKT_ALIAS_LOG;
952 if (x & NG_NAT_DENY_INCOMING)
953 res |= PKT_ALIAS_DENY_INCOMING;
954 if (x & NG_NAT_SAME_PORTS)
955 res |= PKT_ALIAS_SAME_PORTS;
956 if (x & NG_NAT_UNREGISTERED_ONLY)
957 res |= PKT_ALIAS_UNREGISTERED_ONLY;
958 if (x & NG_NAT_RESET_ON_ADDR_CHANGE)
959 res |= PKT_ALIAS_RESET_ON_ADDR_CHANGE;
960 if (x & NG_NAT_PROXY_ONLY)
961 res |= PKT_ALIAS_PROXY_ONLY;
962 if (x & NG_NAT_REVERSE)
963 res |= PKT_ALIAS_REVERSE;