FreeBSD kernel netgraph code
ng_nat.c
Go to the documentation of this file.
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
9 * are met:
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.
15 *
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
26 * SUCH DAMAGE.
27 *
28 * $FreeBSD$
29 */
30
31#include <sys/param.h>
32#include <sys/systm.h>
33#include <sys/kernel.h>
34#include <sys/mbuf.h>
35#include <sys/malloc.h>
36#include <sys/ctype.h>
37#include <sys/errno.h>
38#include <sys/syslog.h>
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
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
64
65static unsigned int ng_nat_translate_flags(unsigned int x);
66
67/* Parse type for struct ng_nat_mode. */
70static const struct ng_parse_type ng_nat_mode_type = {
73};
74
75/* Parse type for 'description' field in structs. */
81};
82
83/* Parse type for struct ng_nat_redirect_port. */
89};
90
91/* Parse type for struct ng_nat_redirect_addr. */
97};
98
99/* Parse type for struct ng_nat_redirect_proto. */
105};
106
107/* Parse type for struct ng_nat_add_server. */
113};
114
115/* Parse type for one struct ng_nat_listrdrs_entry. */
121};
122
123/* Parse type for 'redirects' array in struct ng_nat_list_redirects. */
124static int
126 const u_char *start, const u_char *buf)
127{
128 const struct ng_nat_list_redirects *lr;
129
130 lr = (const struct ng_nat_list_redirects *)
131 (buf - offsetof(struct ng_nat_list_redirects, redirects));
132 return lr->total_count;
133}
134
138 NULL
139};
143};
144
145/* Parse type for struct ng_nat_list_redirects. */
151};
152
153/* Parse type for struct ng_nat_libalias_info. */
159};
160
161/* List of commands and how to convert arguments to/from ASCII. */
162static const struct ng_cmdlist ng_nat_cmdlist[] = {
163 {
166 "setaliasaddr",
168 NULL
169 },
170 {
173 "setmode",
175 NULL
176 },
177 {
180 "settarget",
182 NULL
183 },
184 {
187 "redirectport",
190 },
191 {
194 "redirectaddr",
197 },
198 {
201 "redirectproto",
204 },
205 {
208 "redirectdynamic",
210 NULL
211 },
212 {
215 "redirectdelete",
217 NULL
218 },
219 {
222 "addserver",
224 NULL
225 },
226 {
229 "listredirects",
230 NULL,
232 },
233 {
236 "proxyrule",
238 NULL
239 },
240 {
243 "libaliasinfo",
244 NULL,
246 },
247 {
250 "setdlt",
252 NULL
253 },
254 {
257 "getdlt",
258 NULL,
260 },
261 { 0 }
262};
263
264/* Netgraph node type descriptor. */
265static struct ng_type typestruct = {
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,
275};
277MODULE_DEPEND(ng_nat, libalias, 1, 1, 1);
278
279/* Element for list of redirects. */
281 STAILQ_ENTRY(ng_nat_rdr_lst) entries;
282 struct alias_link *lnk;
283 struct ng_nat_listrdrs_entry rdr;
284};
286
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 */
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
307{
308 priv_p priv;
309
310 /* Initialize private descriptor. */
311 priv = malloc(sizeof(*priv), M_NETGRAPH, M_WAITOK | M_ZERO);
312
313 /* Init aliasing engine. */
314 priv->lib = LibAliasInit(NULL);
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;
324 STAILQ_INIT(&priv->redirhead);
325
326 /* Link structs together. */
328 priv->node = node;
329
330 /*
331 * libalias is not thread safe, so our node
332 * must be single threaded.
333 */
335
336 return (0);
337}
338
339static int
341{
343
344 if (strcmp(name, NG_NAT_HOOK_IN) == 0) {
345 priv->in = hook;
346 } else if (strcmp(name, NG_NAT_HOOK_OUT) == 0) {
347 priv->out = hook;
348 } else
349 return (EINVAL);
350
351 if (priv->out != NULL &&
352 priv->in != NULL)
353 priv->flags |= NGNAT_CONNECTED;
354
355 return(0);
356}
357
358static int
360{
362 struct ng_mesg *resp = NULL;
363 struct ng_mesg *msg;
364 int error = 0;
365
366 NGI_GET_MSG(item, msg);
367
368 switch (msg->header.typecookie) {
369 case NGM_NAT_COOKIE:
370 switch (msg->header.cmd) {
372 {
373 struct in_addr *const ia = (struct in_addr *)msg->data;
374
375 if (msg->header.arglen < sizeof(*ia)) {
376 error = EINVAL;
377 break;
378 }
379
380 LibAliasSetAddress(priv->lib, *ia);
381
382 priv->flags |= NGNAT_ADDR_DEFINED;
383 }
384 break;
385 case NGM_NAT_SET_MODE:
386 {
387 struct ng_nat_mode *const mode =
388 (struct ng_nat_mode *)msg->data;
389
390 if (msg->header.arglen < sizeof(*mode)) {
391 error = EINVAL;
392 break;
393 }
394
395 if (LibAliasSetMode(priv->lib,
397 ng_nat_translate_flags(mode->mask)) < 0) {
398 error = ENOMEM;
399 break;
400 }
401 }
402 break;
404 {
405 struct in_addr *const ia = (struct in_addr *)msg->data;
406
407 if (msg->header.arglen < sizeof(*ia)) {
408 error = EINVAL;
409 break;
410 }
411
412 LibAliasSetTarget(priv->lib, *ia);
413 }
414 break;
416 {
417 struct ng_nat_rdr_lst *entry;
418 struct ng_nat_redirect_port *const rp =
419 (struct ng_nat_redirect_port *)msg->data;
420
421 if (msg->header.arglen < sizeof(*rp)) {
422 error = EINVAL;
423 break;
424 }
425
426 if ((entry = malloc(sizeof(struct ng_nat_rdr_lst),
427 M_NETGRAPH, M_NOWAIT | M_ZERO)) == NULL) {
428 error = ENOMEM;
429 break;
430 }
431
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),
437 rp->proto);
438
439 if (entry->lnk == NULL) {
440 error = ENOMEM;
441 free(entry, M_NETGRAPH);
442 break;
443 }
444
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,
455
456 /* Safety precaution. */
457 entry->rdr.description[NG_NAT_DESC_LENGTH-1] = '\0';
458
459 entry->rdr.id = priv->nextid++;
460 priv->rdrcount++;
461
462 /* Link to list of redirects. */
463 STAILQ_INSERT_TAIL(&priv->redirhead, entry, entries);
464
465 /* Response with id of newly added entry. */
466 NG_MKRESPONSE(resp, msg, sizeof(entry->rdr.id), M_NOWAIT);
467 if (resp == NULL) {
468 error = ENOMEM;
469 break;
470 }
471 bcopy(&entry->rdr.id, resp->data, sizeof(entry->rdr.id));
472 }
473 break;
475 {
476 struct ng_nat_rdr_lst *entry;
477 struct ng_nat_redirect_addr *const ra =
478 (struct ng_nat_redirect_addr *)msg->data;
479
480 if (msg->header.arglen < sizeof(*ra)) {
481 error = EINVAL;
482 break;
483 }
484
485 if ((entry = malloc(sizeof(struct ng_nat_rdr_lst),
486 M_NETGRAPH, M_NOWAIT | M_ZERO)) == NULL) {
487 error = ENOMEM;
488 break;
489 }
490
491 /* Try actual redirect. */
492 entry->lnk = LibAliasRedirectAddr(priv->lib,
493 ra->local_addr, ra->alias_addr);
494
495 if (entry->lnk == NULL) {
496 error = ENOMEM;
497 free(entry, M_NETGRAPH);
498 break;
499 }
500
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,
507
508 /* Safety precaution. */
509 entry->rdr.description[NG_NAT_DESC_LENGTH-1] = '\0';
510
511 entry->rdr.id = priv->nextid++;
512 priv->rdrcount++;
513
514 /* Link to list of redirects. */
515 STAILQ_INSERT_TAIL(&priv->redirhead, entry, entries);
516
517 /* Response with id of newly added entry. */
518 NG_MKRESPONSE(resp, msg, sizeof(entry->rdr.id), M_NOWAIT);
519 if (resp == NULL) {
520 error = ENOMEM;
521 break;
522 }
523 bcopy(&entry->rdr.id, resp->data, sizeof(entry->rdr.id));
524 }
525 break;
527 {
528 struct ng_nat_rdr_lst *entry;
529 struct ng_nat_redirect_proto *const rp =
530 (struct ng_nat_redirect_proto *)msg->data;
531
532 if (msg->header.arglen < sizeof(*rp)) {
533 error = EINVAL;
534 break;
535 }
536
537 if ((entry = malloc(sizeof(struct ng_nat_rdr_lst),
538 M_NETGRAPH, M_NOWAIT | M_ZERO)) == NULL) {
539 error = ENOMEM;
540 break;
541 }
542
543 /* Try actual redirect. */
544 entry->lnk = LibAliasRedirectProto(priv->lib,
545 rp->local_addr, rp->remote_addr,
546 rp->alias_addr, rp->proto);
547
548 if (entry->lnk == NULL) {
549 error = ENOMEM;
550 free(entry, M_NETGRAPH);
551 break;
552 }
553
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,
561
562 /* Safety precaution. */
563 entry->rdr.description[NG_NAT_DESC_LENGTH-1] = '\0';
564
565 entry->rdr.id = priv->nextid++;
566 priv->rdrcount++;
567
568 /* Link to list of redirects. */
569 STAILQ_INSERT_TAIL(&priv->redirhead, entry, entries);
570
571 /* Response with id of newly added entry. */
572 NG_MKRESPONSE(resp, msg, sizeof(entry->rdr.id), M_NOWAIT);
573 if (resp == NULL) {
574 error = ENOMEM;
575 break;
576 }
577 bcopy(&entry->rdr.id, resp->data, sizeof(entry->rdr.id));
578 }
579 break;
582 {
583 struct ng_nat_rdr_lst *entry;
584 uint32_t *const id = (uint32_t *)msg->data;
585
586 if (msg->header.arglen < sizeof(*id)) {
587 error = EINVAL;
588 break;
589 }
590
591 /* Find entry with supplied id. */
592 STAILQ_FOREACH(entry, &priv->redirhead, entries) {
593 if (entry->rdr.id == *id)
594 break;
595 }
596
597 /* Not found. */
598 if (entry == NULL) {
599 error = ENOENT;
600 break;
601 }
602
603 if (msg->header.cmd == NGM_NAT_REDIRECT_DYNAMIC) {
604 if (LibAliasRedirectDynamic(priv->lib,
605 entry->lnk) == -1) {
606 error = ENOTTY; /* XXX Something better? */
607 break;
608 }
609 } else { /* NGM_NAT_REDIRECT_DELETE */
610 LibAliasRedirectDelete(priv->lib, entry->lnk);
611 }
612
613 /* Delete entry from our internal list. */
614 priv->rdrcount--;
615 STAILQ_REMOVE(&priv->redirhead, entry, ng_nat_rdr_lst, entries);
616 free(entry, M_NETGRAPH);
617 }
618 break;
620 {
621 struct ng_nat_rdr_lst *entry;
622 struct ng_nat_add_server *const as =
623 (struct ng_nat_add_server *)msg->data;
624
625 if (msg->header.arglen < sizeof(*as)) {
626 error = EINVAL;
627 break;
628 }
629
630 /* Find entry with supplied id. */
631 STAILQ_FOREACH(entry, &priv->redirhead, entries) {
632 if (entry->rdr.id == as->id)
633 break;
634 }
635
636 /* Not found. */
637 if (entry == NULL) {
638 error = ENOENT;
639 break;
640 }
641
642 if (LibAliasAddServer(priv->lib, entry->lnk,
643 as->addr, htons(as->port)) == -1) {
644 error = ENOMEM;
645 break;
646 }
647
648 entry->rdr.lsnat++;
649 }
650 break;
652 {
653 struct ng_nat_rdr_lst *entry;
654 struct ng_nat_list_redirects *ary;
655 int i = 0;
656
657 NG_MKRESPONSE(resp, msg, sizeof(*ary) +
658 (priv->rdrcount) * sizeof(*entry), M_NOWAIT);
659 if (resp == NULL) {
660 error = ENOMEM;
661 break;
662 }
663
664 ary = (struct ng_nat_list_redirects *)resp->data;
665 ary->total_count = priv->rdrcount;
666
667 STAILQ_FOREACH(entry, &priv->redirhead, entries) {
668 bcopy(&entry->rdr, &ary->redirects[i++],
669 sizeof(struct ng_nat_listrdrs_entry));
670 }
671 }
672 break;
674 {
675 char *cmd = (char *)msg->data;
676
677 if (msg->header.arglen < 6) {
678 error = EINVAL;
679 break;
680 }
681
682 if (LibAliasProxyRule(priv->lib, cmd) != 0)
683 error = ENOMEM;
684 }
685 break;
687 {
688 struct ng_nat_libalias_info *i;
689
690 NG_MKRESPONSE(resp, msg,
691 sizeof(struct ng_nat_libalias_info), M_NOWAIT);
692 if (resp == NULL) {
693 error = ENOMEM;
694 break;
695 }
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; \
700 else \
701 i->F = UINT32_MAX; \
702} while (0)
703
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;
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;
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
756{
758 struct mbuf *m;
759 struct ip *ip;
760 int rval, ipofs, error = 0;
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
769 /* We have no alias address yet to do anything. */
770 if (!(priv->flags & NGNAT_ADDR_DEFINED))
771 goto send;
772
773 m = NGI_M(item);
774
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
783 switch (priv->dlt) {
784 case DLT_RAW:
785 ipofs = 0;
786 break;
787 case DLT_EN10MB:
788 {
789 struct ether_header *eh;
790
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 ipofs = sizeof(struct ether_header);
799 break;
800 default:
801 goto send;
802 }
803 break;
804 }
805 default:
806 panic("Corrupted priv->dlt: %u", priv->dlt);
807 }
808
809 if (m->m_pkthdr.len < ipofs + sizeof(struct ip))
810 goto send; /* packet too short to hold IP */
811
812 c = (char *)mtodo(m, ipofs);
813 ip = (struct ip *)mtodo(m, ipofs);
814
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) */
819
820 /*
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.
827 */
828 if (hook == priv->in) {
829 rval = LibAliasIn(priv->lib, c, m->m_len - ipofs +
830 M_TRAILINGSPACE(m));
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)) {
836 NG_FREE_ITEM(item);
837 return (EINVAL);
838 }
839 } else if (hook == priv->out) {
840 rval = LibAliasOut(priv->lib, c, m->m_len - ipofs +
841 M_TRAILINGSPACE(m));
842 if (rval == PKT_ALIAS_ERROR) {
843 NG_FREE_ITEM(item);
844 return (EINVAL);
845 }
846 } else
847 panic("ng_nat: unknown hook!\n");
848
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;
852
853 if ((ip->ip_off & htons(IP_OFFMASK)) == 0 &&
854 ip->ip_p == IPPROTO_TCP) {
855 struct tcphdr *th = (struct tcphdr *)((caddr_t)ip +
856 (ip->ip_hl << 2));
857
858 /*
859 * Here is our terrible HACK.
860 *
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.
870 *
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.
878 */
879
880 if (th->th_x2) {
881 uint16_t ip_len = ntohs(ip->ip_len);
882
883 th->th_x2 = 0;
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)));
887
888 if ((m->m_pkthdr.csum_flags & CSUM_TCP) == 0) {
889 m->m_pkthdr.csum_data = offsetof(struct tcphdr,
890 th_sum);
891 in_delayed_cksum(m);
892 }
893 }
894 }
895
896send:
897 if (hook == priv->in)
898 NG_FWD_ITEM_HOOK(error, item, priv->out);
899 else
900 NG_FWD_ITEM_HOOK(error, item, priv->in);
901
902 return (error);
903}
904
905static int
907{
908 const priv_p priv = NG_NODE_PRIVATE(node);
909
910 NG_NODE_SET_PRIVATE(node, NULL);
911 NG_NODE_UNREF(node);
912
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);
918 }
919
920 /* Final free. */
921 LibAliasUninit(priv->lib);
922 free(priv, M_NETGRAPH);
923
924 return (0);
925}
926
927static int
929{
931
932 priv->flags &= ~NGNAT_CONNECTED;
933
934 if (hook == priv->out)
935 priv->out = NULL;
936 if (hook == priv->in)
937 priv->in = NULL;
938
939 if (priv->out == NULL && priv->in == NULL)
941
942 return (0);
943}
944
945static unsigned int
947{
948 unsigned int res = 0;
949
950 if (x & NG_NAT_LOG)
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;
957 res |= PKT_ALIAS_UNREGISTERED_ONLY;
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;
965 res |= PKT_ALIAS_UNREGISTERED_CGN;
966
967 return (res);
968}
#define NGI_M(i)
Definition: netgraph.h:833
#define NG_HOOK_NODE(hook)
Definition: netgraph.h:339
int ng_rcvmsg_t(node_p node, item_p item, hook_p lasthook)
Definition: netgraph.h:105
#define NG_FWD_ITEM_HOOK(error, item, hook)
Definition: netgraph.h:898
int ng_disconnect_t(hook_p hook)
Definition: netgraph.h:107
#define NG_NODE_SET_PRIVATE(node, val)
Definition: netgraph.h:608
#define NG_RESPOND_MSG(error, here, item, resp)
Definition: netgraph.h:1025
#define NG_NODE_FORCE_WRITER(node)
Definition: netgraph.h:612
#define NG_NODE_UNREF(node)
Definition: netgraph.h:607
int ng_rmnode_self(node_p here)
Definition: ng_base.c:1609
int ng_rcvdata_t(hook_p hook, item_p item)
Definition: netgraph.h:106
int ng_shutdown_t(node_p node)
Definition: netgraph.h:101
#define NG_FREE_ITEM(item)
Definition: netgraph.h:847
int ng_constructor_t(node_p node)
Definition: netgraph.h:99
#define NG_FREE_MSG(msg)
Definition: netgraph.h:938
#define NG_ABI_VERSION
Definition: netgraph.h:77
#define NGI_GET_MSG(i, m)
Definition: netgraph.h:858
#define NG_NODE_PRIVATE(node)
Definition: netgraph.h:609
int ng_newhook_t(node_p node, hook_p hook, const char *name)
Definition: netgraph.h:102
u_int8_t type
#define NG_MKRESPONSE(rsp, msg, len, how)
Definition: ng_message.h:396
static const struct ng_parse_array_info ng_nat_listrdrs_ary_info
Definition: ng_nat.c:135
static const struct ng_parse_struct_field ng_nat_libalias_info_fields[]
Definition: ng_nat.c:155
struct ng_nat_priv * priv_p
Definition: ng_nat.c:299
NETGRAPH_INIT(nat, &typestruct)
static unsigned int ng_nat_translate_flags(unsigned int x)
Definition: ng_nat.c:946
static ng_disconnect_t ng_nat_disconnect
Definition: ng_nat.c:63
static const struct ng_cmdlist ng_nat_cmdlist[]
Definition: ng_nat.c:162
static const struct ng_parse_fixedstring_info ng_nat_description_info
Definition: ng_nat.c:77
static const struct ng_parse_type ng_nat_mode_type
Definition: ng_nat.c:70
static const struct ng_parse_struct_field ng_nat_list_redirects_fields[]
Definition: ng_nat.c:147
static ng_rcvdata_t ng_nat_rcvdata
Definition: ng_nat.c:62
static ng_rcvmsg_t ng_nat_rcvmsg
Definition: ng_nat.c:59
static const struct ng_parse_type ng_nat_libalias_info_type
Definition: ng_nat.c:156
static ng_constructor_t ng_nat_constructor
Definition: ng_nat.c:58
static const struct ng_parse_type ng_nat_listrdrs_ary_type
Definition: ng_nat.c:140
static const struct ng_parse_type ng_nat_redirect_addr_type
Definition: ng_nat.c:94
#define NGNAT_CONNECTED
Definition: ng_nat.c:302
static ng_shutdown_t ng_nat_shutdown
Definition: ng_nat.c:60
static const struct ng_parse_type ng_nat_redirect_proto_type
Definition: ng_nat.c:102
static int ng_nat_listrdrs_ary_getLength(const struct ng_parse_type *type, const u_char *start, const u_char *buf)
Definition: ng_nat.c:125
static const struct ng_parse_struct_field ng_nat_redirect_port_fields[]
Definition: ng_nat.c:85
#define COPY(F)
static const struct ng_parse_type ng_nat_description_type
Definition: ng_nat.c:78
static struct ng_type typestruct
Definition: ng_nat.c:265
static const struct ng_parse_type ng_nat_add_server_type
Definition: ng_nat.c:110
static const struct ng_parse_struct_field ng_nat_listrdrs_entry_fields[]
Definition: ng_nat.c:117
static const struct ng_parse_type ng_nat_list_redirects_type
Definition: ng_nat.c:148
static ng_newhook_t ng_nat_newhook
Definition: ng_nat.c:61
#define NGNAT_ADDR_DEFINED
Definition: ng_nat.c:303
static const struct ng_parse_struct_field ng_nat_mode_fields[]
Definition: ng_nat.c:69
STAILQ_HEAD(rdrhead, ng_nat_rdr_lst)
static const struct ng_parse_struct_field ng_nat_add_server_fields[]
Definition: ng_nat.c:109
static const struct ng_parse_struct_field ng_nat_redirect_proto_fields[]
Definition: ng_nat.c:101
static const struct ng_parse_type ng_nat_redirect_port_type
Definition: ng_nat.c:86
static const struct ng_parse_struct_field ng_nat_redirect_addr_fields[]
Definition: ng_nat.c:93
static const struct ng_parse_type ng_nat_listrdrs_entry_type
Definition: ng_nat.c:118
MODULE_DEPEND(ng_nat, libalias, 1, 1, 1)
#define NG_NAT_HOOK_IN
Definition: ng_nat.h:34
#define NG_NAT_HOOK_OUT
Definition: ng_nat.h:35
#define NG_NAT_UNREGISTERED_ONLY
Definition: ng_nat.h:53
#define NGM_NAT_COOKIE
Definition: ng_nat.h:32
#define NG_NAT_DENY_INCOMING
Definition: ng_nat.h:51
#define NG_NAT_PROXY_ONLY
Definition: ng_nat.h:55
#define NG_NAT_LOG
Definition: ng_nat.h:50
#define NG_NAT_REDIRECT_PROTO_TYPE_INFO(desctype)
Definition: ng_nat.h:112
#define NG_NAT_MODE_INFO
Definition: ng_nat.h:44
#define NG_NAT_ADD_SERVER_TYPE_INFO
Definition: ng_nat.h:129
#define NG_NAT_LISTRDRS_ENTRY_TYPE_INFO(desctype)
Definition: ng_nat.h:151
#define NG_NAT_REVERSE
Definition: ng_nat.h:56
#define NG_NAT_REDIRECT_ADDR_TYPE_INFO(desctype)
Definition: ng_nat.h:95
#define NG_NAT_DESC_LENGTH
Definition: ng_nat.h:59
#define NG_NAT_UNREGISTERED_CGN
Definition: ng_nat.h:57
#define NG_NAT_LIBALIAS_INFO
Definition: ng_nat.h:192
#define NG_NAT_NODE_TYPE
Definition: ng_nat.h:31
#define NG_NAT_REDIRECT_PORT_TYPE_INFO(desctype)
Definition: ng_nat.h:75
#define NG_NAT_REDIRPROTO_ADDR
Definition: ng_nat.h:60
#define NG_NAT_LIST_REDIRECTS_TYPE_INFO(redirtype)
Definition: ng_nat.h:172
#define NG_NAT_SAME_PORTS
Definition: ng_nat.h:52
#define NG_NAT_RESET_ON_ADDR_CHANGE
Definition: ng_nat.h:54
@ NGM_NAT_ADD_SERVER
Definition: ng_nat.h:214
@ NGM_NAT_SET_DLT
Definition: ng_nat.h:218
@ NGM_NAT_SET_TARGET
Definition: ng_nat.h:208
@ NGM_NAT_SET_IPADDR
Definition: ng_nat.h:206
@ NGM_NAT_LIST_REDIRECTS
Definition: ng_nat.h:215
@ NGM_NAT_SET_MODE
Definition: ng_nat.h:207
@ NGM_NAT_REDIRECT_PORT
Definition: ng_nat.h:209
@ NGM_NAT_GET_DLT
Definition: ng_nat.h:219
@ NGM_NAT_REDIRECT_ADDR
Definition: ng_nat.h:210
@ NGM_NAT_LIBALIAS_INFO
Definition: ng_nat.h:217
@ NGM_NAT_REDIRECT_DYNAMIC
Definition: ng_nat.h:212
@ NGM_NAT_REDIRECT_PROTO
Definition: ng_nat.h:211
@ NGM_NAT_PROXY_RULE
Definition: ng_nat.h:216
@ NGM_NAT_REDIRECT_DELETE
Definition: ng_nat.h:213
const struct ng_parse_type ng_parse_fixedstring_type
Definition: ng_parse.c:830
const struct ng_parse_type ng_parse_ipaddr_type
Definition: ng_parse.c:1002
const struct ng_parse_type ng_parse_array_type
Definition: ng_parse.c:318
const struct ng_parse_type ng_parse_string_type
Definition: ng_parse.c:766
const struct ng_parse_type ng_parse_struct_type
Definition: ng_parse.c:222
const struct ng_parse_type ng_parse_uint32_type
Definition: ng_parse.c:608
const struct ng_parse_type ng_parse_uint8_type
Definition: ng_parse.c:413
char *const name
Definition: ng_ppp.c:261
cmd
Definition: ng_pppoe.h:74
u_int32_t arglen
Definition: ng_message.h:62
u_int32_t typecookie
Definition: ng_message.h:66
struct ng_mesg::ng_msghdr header
char data[]
Definition: ng_message.h:69
uint32_t id
Definition: ng_nat.h:123
uint16_t port
Definition: ng_nat.h:125
struct in_addr addr
Definition: ng_nat.h:124
uint32_t sockCount
Definition: ng_nat.h:188
uint32_t icmpLinkCount
Definition: ng_nat.h:180
uint32_t udpLinkCount
Definition: ng_nat.h:181
uint32_t protoLinkCount
Definition: ng_nat.h:185
uint32_t pptpLinkCount
Definition: ng_nat.h:184
uint32_t fragmentPtrLinkCount
Definition: ng_nat.h:187
uint32_t fragmentIdLinkCount
Definition: ng_nat.h:186
uint32_t sctpLinkCount
Definition: ng_nat.h:183
uint32_t tcpLinkCount
Definition: ng_nat.h:182
uint32_t total_count
Definition: ng_nat.h:167
struct ng_nat_listrdrs_entry redirects[]
Definition: ng_nat.h:168
Definition: ng_nat.h:137
uint32_t flags
Definition: ng_nat.h:39
uint32_t mask
Definition: ng_nat.h:40
struct rdrhead redirhead
Definition: ng_nat.c:296
uint32_t rdrcount
Definition: ng_nat.c:294
hook_p out
Definition: ng_nat.c:291
hook_p in
Definition: ng_nat.c:290
uint32_t nextid
Definition: ng_nat.c:295
node_p node
Definition: ng_nat.c:289
uint32_t flags
Definition: ng_nat.c:293
struct libalias * lib
Definition: ng_nat.c:292
uint8_t dlt
Definition: ng_nat.c:297
struct in_addr alias_addr
Definition: ng_nat.h:90
struct in_addr local_addr
Definition: ng_nat.h:89
char description[NG_NAT_DESC_LENGTH]
Definition: ng_nat.h:91
struct in_addr remote_addr
Definition: ng_nat.h:66
uint16_t alias_port
Definition: ng_nat.h:68
struct in_addr local_addr
Definition: ng_nat.h:64
struct in_addr alias_addr
Definition: ng_nat.h:65
char description[NG_NAT_DESC_LENGTH]
Definition: ng_nat.h:71
uint16_t local_port
Definition: ng_nat.h:67
uint16_t remote_port
Definition: ng_nat.h:69
char description[NG_NAT_DESC_LENGTH]
Definition: ng_nat.h:108
struct in_addr remote_addr
Definition: ng_nat.h:106
struct in_addr alias_addr
Definition: ng_nat.h:105
struct in_addr local_addr
Definition: ng_nat.h:104
u_int32_t version
Definition: netgraph.h:1077
Definition: ng_sscfu.c:66