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>
47 #include <netinet/libalias/alias.h>
48 #include <netinet/libalias/alias_local.h>
50 #include <netgraph/ng_message.h>
51 #include <netgraph/ng_parse.h>
52 #include <netgraph/ng_nat.h>
53 #include <netgraph/netgraph.h>
55 static ng_constructor_t ng_nat_constructor;
56 static ng_rcvmsg_t ng_nat_rcvmsg;
57 static ng_shutdown_t ng_nat_shutdown;
58 static ng_newhook_t ng_nat_newhook;
59 static ng_rcvdata_t ng_nat_rcvdata;
60 static ng_disconnect_t ng_nat_disconnect;
62 static unsigned int ng_nat_translate_flags(unsigned int x);
64 /* Parse type for struct ng_nat_mode. */
65 static const struct ng_parse_struct_field ng_nat_mode_fields[]
67 static const struct ng_parse_type ng_nat_mode_type = {
68 &ng_parse_struct_type,
72 /* Parse type for 'description' field in structs. */
73 static const struct ng_parse_fixedstring_info ng_nat_description_info
74 = { NG_NAT_DESC_LENGTH };
75 static const struct ng_parse_type ng_nat_description_type = {
76 &ng_parse_fixedstring_type,
77 &ng_nat_description_info
80 /* Parse type for struct ng_nat_redirect_port. */
81 static const struct ng_parse_struct_field ng_nat_redirect_port_fields[]
82 = NG_NAT_REDIRECT_PORT_TYPE_INFO(&ng_nat_description_type);
83 static const struct ng_parse_type ng_nat_redirect_port_type = {
84 &ng_parse_struct_type,
85 &ng_nat_redirect_port_fields
88 /* Parse type for struct ng_nat_redirect_addr. */
89 static const struct ng_parse_struct_field ng_nat_redirect_addr_fields[]
90 = NG_NAT_REDIRECT_ADDR_TYPE_INFO(&ng_nat_description_type);
91 static const struct ng_parse_type ng_nat_redirect_addr_type = {
92 &ng_parse_struct_type,
93 &ng_nat_redirect_addr_fields
96 /* Parse type for struct ng_nat_redirect_proto. */
97 static const struct ng_parse_struct_field ng_nat_redirect_proto_fields[]
98 = NG_NAT_REDIRECT_PROTO_TYPE_INFO(&ng_nat_description_type);
99 static const struct ng_parse_type ng_nat_redirect_proto_type = {
100 &ng_parse_struct_type,
101 &ng_nat_redirect_proto_fields
104 /* Parse type for struct ng_nat_add_server. */
105 static const struct ng_parse_struct_field ng_nat_add_server_fields[]
106 = NG_NAT_ADD_SERVER_TYPE_INFO;
107 static const struct ng_parse_type ng_nat_add_server_type = {
108 &ng_parse_struct_type,
109 &ng_nat_add_server_fields
112 /* Parse type for one struct ng_nat_listrdrs_entry. */
113 static const struct ng_parse_struct_field ng_nat_listrdrs_entry_fields[]
114 = NG_NAT_LISTRDRS_ENTRY_TYPE_INFO(&ng_nat_description_type);
115 static const struct ng_parse_type ng_nat_listrdrs_entry_type = {
116 &ng_parse_struct_type,
117 &ng_nat_listrdrs_entry_fields
120 /* Parse type for 'redirects' array in struct ng_nat_list_redirects. */
122 ng_nat_listrdrs_ary_getLength(const struct ng_parse_type *type,
123 const u_char *start, const u_char *buf)
125 const struct ng_nat_list_redirects *lr;
127 lr = (const struct ng_nat_list_redirects *)
128 (buf - offsetof(struct ng_nat_list_redirects, redirects));
129 return lr->total_count;
132 static const struct ng_parse_array_info ng_nat_listrdrs_ary_info = {
133 &ng_nat_listrdrs_entry_type,
134 &ng_nat_listrdrs_ary_getLength,
137 static const struct ng_parse_type ng_nat_listrdrs_ary_type = {
138 &ng_parse_array_type,
139 &ng_nat_listrdrs_ary_info
142 /* Parse type for struct ng_nat_list_redirects. */
143 static const struct ng_parse_struct_field ng_nat_list_redirects_fields[]
144 = NG_NAT_LIST_REDIRECTS_TYPE_INFO(&ng_nat_listrdrs_ary_type);
145 static const struct ng_parse_type ng_nat_list_redirects_type = {
146 &ng_parse_struct_type,
147 &ng_nat_list_redirects_fields
150 /* Parse type for struct ng_nat_libalias_info. */
151 static const struct ng_parse_struct_field ng_nat_libalias_info_fields[]
152 = NG_NAT_LIBALIAS_INFO;
153 static const struct ng_parse_type ng_nat_libalias_info_type = {
154 &ng_parse_struct_type,
155 &ng_nat_libalias_info_fields
158 /* List of commands and how to convert arguments to/from ASCII. */
159 static const struct ng_cmdlist ng_nat_cmdlist[] = {
164 &ng_parse_ipaddr_type,
178 &ng_parse_ipaddr_type,
183 NGM_NAT_REDIRECT_PORT,
185 &ng_nat_redirect_port_type,
186 &ng_parse_uint32_type
190 NGM_NAT_REDIRECT_ADDR,
192 &ng_nat_redirect_addr_type,
193 &ng_parse_uint32_type
197 NGM_NAT_REDIRECT_PROTO,
199 &ng_nat_redirect_proto_type,
200 &ng_parse_uint32_type
204 NGM_NAT_REDIRECT_DYNAMIC,
206 &ng_parse_uint32_type,
211 NGM_NAT_REDIRECT_DELETE,
213 &ng_parse_uint32_type,
220 &ng_nat_add_server_type,
225 NGM_NAT_LIST_REDIRECTS,
228 &ng_nat_list_redirects_type
234 &ng_parse_string_type,
239 NGM_NAT_LIBALIAS_INFO,
242 &ng_nat_libalias_info_type
247 /* Netgraph node type descriptor. */
248 static struct ng_type typestruct = {
249 .version = NG_ABI_VERSION,
250 .name = NG_NAT_NODE_TYPE,
251 .constructor = ng_nat_constructor,
252 .rcvmsg = ng_nat_rcvmsg,
253 .shutdown = ng_nat_shutdown,
254 .newhook = ng_nat_newhook,
255 .rcvdata = ng_nat_rcvdata,
256 .disconnect = ng_nat_disconnect,
257 .cmdlist = ng_nat_cmdlist,
259 NETGRAPH_INIT(nat, &typestruct);
260 MODULE_DEPEND(ng_nat, libalias, 1, 1, 1);
262 /* Element for list of redirects. */
263 struct ng_nat_rdr_lst {
264 STAILQ_ENTRY(ng_nat_rdr_lst) entries;
265 struct alias_link *lnk;
266 struct ng_nat_listrdrs_entry rdr;
268 STAILQ_HEAD(rdrhead, ng_nat_rdr_lst);
270 /* Information we store for each node. */
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 */
281 typedef struct ng_nat_priv *priv_p;
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 */
288 ng_nat_constructor(node_p node)
292 /* Initialize private descriptor. */
293 priv = malloc(sizeof(*priv), M_NETGRAPH, M_WAITOK | M_ZERO);
295 /* Init aliasing engine. */
296 priv->lib = LibAliasInit(NULL);
298 /* Set same ports on. */
299 (void )LibAliasSetMode(priv->lib, PKT_ALIAS_SAME_PORTS,
300 PKT_ALIAS_SAME_PORTS);
302 /* Init redirects housekeeping. */
305 STAILQ_INIT(&priv->redirhead);
307 /* Link structs together. */
308 NG_NODE_SET_PRIVATE(node, priv);
312 * libalias is not thread safe, so our node
313 * must be single threaded.
315 NG_NODE_FORCE_WRITER(node);
321 ng_nat_newhook(node_p node, hook_p hook, const char *name)
323 const priv_p priv = NG_NODE_PRIVATE(node);
325 if (strcmp(name, NG_NAT_HOOK_IN) == 0) {
327 } else if (strcmp(name, NG_NAT_HOOK_OUT) == 0) {
332 if (priv->out != NULL &&
334 priv->flags |= NGNAT_CONNECTED;
340 ng_nat_rcvmsg(node_p node, item_p item, hook_p lasthook)
342 const priv_p priv = NG_NODE_PRIVATE(node);
343 struct ng_mesg *resp = NULL;
347 NGI_GET_MSG(item, msg);
349 switch (msg->header.typecookie) {
351 switch (msg->header.cmd) {
352 case NGM_NAT_SET_IPADDR:
354 struct in_addr *const ia = (struct in_addr *)msg->data;
356 if (msg->header.arglen < sizeof(*ia)) {
361 LibAliasSetAddress(priv->lib, *ia);
363 priv->flags |= NGNAT_ADDR_DEFINED;
366 case NGM_NAT_SET_MODE:
368 struct ng_nat_mode *const mode =
369 (struct ng_nat_mode *)msg->data;
371 if (msg->header.arglen < sizeof(*mode)) {
376 if (LibAliasSetMode(priv->lib,
377 ng_nat_translate_flags(mode->flags),
378 ng_nat_translate_flags(mode->mask)) < 0) {
384 case NGM_NAT_SET_TARGET:
386 struct in_addr *const ia = (struct in_addr *)msg->data;
388 if (msg->header.arglen < sizeof(*ia)) {
393 LibAliasSetTarget(priv->lib, *ia);
396 case NGM_NAT_REDIRECT_PORT:
398 struct ng_nat_rdr_lst *entry;
399 struct ng_nat_redirect_port *const rp =
400 (struct ng_nat_redirect_port *)msg->data;
402 if (msg->header.arglen < sizeof(*rp)) {
407 if ((entry = malloc(sizeof(struct ng_nat_rdr_lst),
408 M_NETGRAPH, M_NOWAIT | M_ZERO)) == NULL) {
413 /* Try actual redirect. */
414 entry->lnk = LibAliasRedirectPort(priv->lib,
415 rp->local_addr, htons(rp->local_port),
416 rp->remote_addr, htons(rp->remote_port),
417 rp->alias_addr, htons(rp->alias_port),
420 if (entry->lnk == NULL) {
422 free(entry, M_NETGRAPH);
426 /* Successful, save info in our internal list. */
427 entry->rdr.local_addr = rp->local_addr;
428 entry->rdr.alias_addr = rp->alias_addr;
429 entry->rdr.remote_addr = rp->remote_addr;
430 entry->rdr.local_port = rp->local_port;
431 entry->rdr.alias_port = rp->alias_port;
432 entry->rdr.remote_port = rp->remote_port;
433 entry->rdr.proto = rp->proto;
434 bcopy(rp->description, entry->rdr.description,
437 /* Safety precaution. */
438 entry->rdr.description[NG_NAT_DESC_LENGTH-1] = '\0';
440 entry->rdr.id = priv->nextid++;
443 /* Link to list of redirects. */
444 STAILQ_INSERT_TAIL(&priv->redirhead, entry, entries);
446 /* Response with id of newly added entry. */
447 NG_MKRESPONSE(resp, msg, sizeof(entry->rdr.id), M_NOWAIT);
452 bcopy(&entry->rdr.id, resp->data, sizeof(entry->rdr.id));
455 case NGM_NAT_REDIRECT_ADDR:
457 struct ng_nat_rdr_lst *entry;
458 struct ng_nat_redirect_addr *const ra =
459 (struct ng_nat_redirect_addr *)msg->data;
461 if (msg->header.arglen < sizeof(*ra)) {
466 if ((entry = malloc(sizeof(struct ng_nat_rdr_lst),
467 M_NETGRAPH, M_NOWAIT | M_ZERO)) == NULL) {
472 /* Try actual redirect. */
473 entry->lnk = LibAliasRedirectAddr(priv->lib,
474 ra->local_addr, ra->alias_addr);
476 if (entry->lnk == NULL) {
478 free(entry, M_NETGRAPH);
482 /* Successful, save info in our internal list. */
483 entry->rdr.local_addr = ra->local_addr;
484 entry->rdr.alias_addr = ra->alias_addr;
485 entry->rdr.proto = NG_NAT_REDIRPROTO_ADDR;
486 bcopy(ra->description, entry->rdr.description,
489 /* Safety precaution. */
490 entry->rdr.description[NG_NAT_DESC_LENGTH-1] = '\0';
492 entry->rdr.id = priv->nextid++;
495 /* Link to list of redirects. */
496 STAILQ_INSERT_TAIL(&priv->redirhead, entry, entries);
498 /* Response with id of newly added entry. */
499 NG_MKRESPONSE(resp, msg, sizeof(entry->rdr.id), M_NOWAIT);
504 bcopy(&entry->rdr.id, resp->data, sizeof(entry->rdr.id));
507 case NGM_NAT_REDIRECT_PROTO:
509 struct ng_nat_rdr_lst *entry;
510 struct ng_nat_redirect_proto *const rp =
511 (struct ng_nat_redirect_proto *)msg->data;
513 if (msg->header.arglen < sizeof(*rp)) {
518 if ((entry = malloc(sizeof(struct ng_nat_rdr_lst),
519 M_NETGRAPH, M_NOWAIT | M_ZERO)) == NULL) {
524 /* Try actual redirect. */
525 entry->lnk = LibAliasRedirectProto(priv->lib,
526 rp->local_addr, rp->remote_addr,
527 rp->alias_addr, rp->proto);
529 if (entry->lnk == NULL) {
531 free(entry, M_NETGRAPH);
535 /* Successful, save info in our internal list. */
536 entry->rdr.local_addr = rp->local_addr;
537 entry->rdr.alias_addr = rp->alias_addr;
538 entry->rdr.remote_addr = rp->remote_addr;
539 entry->rdr.proto = rp->proto;
540 bcopy(rp->description, entry->rdr.description,
543 /* Safety precaution. */
544 entry->rdr.description[NG_NAT_DESC_LENGTH-1] = '\0';
546 entry->rdr.id = priv->nextid++;
549 /* Link to list of redirects. */
550 STAILQ_INSERT_TAIL(&priv->redirhead, entry, entries);
552 /* Response with id of newly added entry. */
553 NG_MKRESPONSE(resp, msg, sizeof(entry->rdr.id), M_NOWAIT);
558 bcopy(&entry->rdr.id, resp->data, sizeof(entry->rdr.id));
561 case NGM_NAT_REDIRECT_DYNAMIC:
562 case NGM_NAT_REDIRECT_DELETE:
564 struct ng_nat_rdr_lst *entry;
565 uint32_t *const id = (uint32_t *)msg->data;
567 if (msg->header.arglen < sizeof(*id)) {
572 /* Find entry with supplied id. */
573 STAILQ_FOREACH(entry, &priv->redirhead, entries) {
574 if (entry->rdr.id == *id)
584 if (msg->header.cmd == NGM_NAT_REDIRECT_DYNAMIC) {
585 if (LibAliasRedirectDynamic(priv->lib,
587 error = ENOTTY; /* XXX Something better? */
590 } else { /* NGM_NAT_REDIRECT_DELETE */
591 LibAliasRedirectDelete(priv->lib, entry->lnk);
594 /* Delete entry from our internal list. */
596 STAILQ_REMOVE(&priv->redirhead, entry, ng_nat_rdr_lst, entries);
597 free(entry, M_NETGRAPH);
600 case NGM_NAT_ADD_SERVER:
602 struct ng_nat_rdr_lst *entry;
603 struct ng_nat_add_server *const as =
604 (struct ng_nat_add_server *)msg->data;
606 if (msg->header.arglen < sizeof(*as)) {
611 /* Find entry with supplied id. */
612 STAILQ_FOREACH(entry, &priv->redirhead, entries) {
613 if (entry->rdr.id == as->id)
623 if (LibAliasAddServer(priv->lib, entry->lnk,
624 as->addr, htons(as->port)) == -1) {
632 case NGM_NAT_LIST_REDIRECTS:
634 struct ng_nat_rdr_lst *entry;
635 struct ng_nat_list_redirects *ary;
638 NG_MKRESPONSE(resp, msg, sizeof(*ary) +
639 (priv->rdrcount) * sizeof(*entry), M_NOWAIT);
645 ary = (struct ng_nat_list_redirects *)resp->data;
646 ary->total_count = priv->rdrcount;
648 STAILQ_FOREACH(entry, &priv->redirhead, entries) {
649 bcopy(&entry->rdr, &ary->redirects[i++],
650 sizeof(struct ng_nat_listrdrs_entry));
654 case NGM_NAT_PROXY_RULE:
656 char *cmd = (char *)msg->data;
658 if (msg->header.arglen < 6) {
663 if (LibAliasProxyRule(priv->lib, cmd) != 0)
667 case NGM_NAT_LIBALIAS_INFO:
669 struct ng_nat_libalias_info *i;
671 NG_MKRESPONSE(resp, msg,
672 sizeof(struct ng_nat_libalias_info), M_NOWAIT);
677 i = (struct ng_nat_libalias_info *)resp->data;
678 #define COPY(F) do { \
679 if (priv->lib->F >= 0 && priv->lib->F < UINT32_MAX) \
680 i->F = priv->lib->F; \
690 COPY(protoLinkCount);
691 COPY(fragmentIdLinkCount);
692 COPY(fragmentPtrLinkCount);
698 error = EINVAL; /* unknown command */
703 error = EINVAL; /* unknown cookie type */
707 NG_RESPOND_MSG(error, node, item, resp);
713 ng_nat_rcvdata(hook_p hook, item_p item )
715 const priv_p priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
721 /* We have no required hooks. */
722 if (!(priv->flags & NGNAT_CONNECTED)) {
727 /* We have no alias address yet to do anything. */
728 if (!(priv->flags & NGNAT_ADDR_DEFINED))
733 if ((m = m_megapullup(m, m->m_pkthdr.len)) == NULL) {
734 NGI_M(item) = NULL; /* avoid double free */
742 ip = mtod(m, struct ip *);
744 KASSERT(m->m_pkthdr.len == ntohs(ip->ip_len),
745 ("ng_nat: ip_len != m_pkthdr.len"));
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.
755 if (hook == priv->in) {
756 rval = LibAliasIn(priv->lib, c, m->m_len + 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)) {
765 } else if (hook == priv->out) {
766 rval = LibAliasOut(priv->lib, c, m->m_len + M_TRAILINGSPACE(m));
767 if (rval == PKT_ALIAS_ERROR) {
772 panic("ng_nat: unknown hook!\n");
774 if (rval == PKT_ALIAS_RESPOND)
775 m->m_flags |= M_SKIP_FIREWALL;
776 m->m_pkthdr.len = m->m_len = ntohs(ip->ip_len);
778 if ((ip->ip_off & htons(IP_OFFMASK)) == 0 &&
779 ip->ip_p == IPPROTO_TCP) {
780 struct tcphdr *th = (struct tcphdr *)((caddr_t)ip +
784 * Here is our terrible HACK.
786 * Sometimes LibAlias edits contents of TCP packet.
787 * In this case it needs to recompute full TCP
788 * checksum. However, the problem is that LibAlias
789 * doesn't have any idea about checksum offloading
790 * in kernel. To workaround this, we do not do
791 * checksumming in LibAlias, but only mark the
792 * packets in th_x2 field. If we receive a marked
793 * packet, we calculate correct checksum for it
794 * aware of offloading.
796 * Why do I do such a terrible hack instead of
797 * recalculating checksum for each packet?
798 * Because the previous checksum was not checked!
799 * Recalculating checksums for EVERY packet will
800 * hide ALL transmission errors. Yes, marked packets
801 * still suffer from this problem. But, sigh, natd(8)
802 * has this problem, too.
806 uint16_t ip_len = ntohs(ip->ip_len);
809 th->th_sum = in_pseudo(ip->ip_src.s_addr,
810 ip->ip_dst.s_addr, htons(IPPROTO_TCP +
811 ip_len - (ip->ip_hl << 2)));
813 if ((m->m_pkthdr.csum_flags & CSUM_TCP) == 0) {
814 m->m_pkthdr.csum_data = offsetof(struct tcphdr,
822 if (hook == priv->in)
823 NG_FWD_ITEM_HOOK(error, item, priv->out);
825 NG_FWD_ITEM_HOOK(error, item, priv->in);
831 ng_nat_shutdown(node_p node)
833 const priv_p priv = NG_NODE_PRIVATE(node);
835 NG_NODE_SET_PRIVATE(node, NULL);
838 /* Free redirects list. */
839 while (!STAILQ_EMPTY(&priv->redirhead)) {
840 struct ng_nat_rdr_lst *entry = STAILQ_FIRST(&priv->redirhead);
841 STAILQ_REMOVE_HEAD(&priv->redirhead, entries);
842 free(entry, M_NETGRAPH);
846 LibAliasUninit(priv->lib);
847 free(priv, M_NETGRAPH);
853 ng_nat_disconnect(hook_p hook)
855 const priv_p priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
857 priv->flags &= ~NGNAT_CONNECTED;
859 if (hook == priv->out)
861 if (hook == priv->in)
864 if (priv->out == NULL && priv->in == NULL)
865 ng_rmnode_self(NG_HOOK_NODE(hook));
871 ng_nat_translate_flags(unsigned int x)
873 unsigned int res = 0;
876 res |= PKT_ALIAS_LOG;
877 if (x & NG_NAT_DENY_INCOMING)
878 res |= PKT_ALIAS_DENY_INCOMING;
879 if (x & NG_NAT_SAME_PORTS)
880 res |= PKT_ALIAS_SAME_PORTS;
881 if (x & NG_NAT_UNREGISTERED_ONLY)
882 res |= PKT_ALIAS_UNREGISTERED_ONLY;
883 if (x & NG_NAT_RESET_ON_ADDR_CHANGE)
884 res |= PKT_ALIAS_RESET_ON_ADDR_CHANGE;
885 if (x & NG_NAT_PROXY_ONLY)
886 res |= PKT_ALIAS_PROXY_ONLY;
887 if (x & NG_NAT_REVERSE)
888 res |= PKT_ALIAS_REVERSE;