diff options
author | Matt Smith <mgsmith@netgate.com> | 2015-11-18 10:28:58 -0600 |
---|---|---|
committer | Matt Smith <mgsmith@netgate.com> | 2015-11-18 10:28:58 -0600 |
commit | 5c536f0cd603578206f12060b6d53bc32a6508a4 (patch) | |
tree | 1ccb9b02d9bc77e64e845d0755cd02eec944ea60 /sbin | |
parent | 999db7254ad92d567efd568383eb4842bd7b409b (diff) | |
download | FreeBSD-src-5c536f0cd603578206f12060b6d53bc32a6508a4.zip FreeBSD-src-5c536f0cd603578206f12060b6d53bc32a6508a4.tar.gz |
Importing pfSense patch CP_multi_instance_ipfw.diff
Diffstat (limited to 'sbin')
-rw-r--r-- | sbin/ipfw/Makefile | 2 | ||||
-rw-r--r-- | sbin/ipfw/context.c | 148 | ||||
-rw-r--r-- | sbin/ipfw/ipfw2.c | 15 | ||||
-rw-r--r-- | sbin/ipfw/ipfw2.h | 4 | ||||
-rw-r--r-- | sbin/ipfw/main.c | 23 |
5 files changed, 187 insertions, 5 deletions
diff --git a/sbin/ipfw/Makefile b/sbin/ipfw/Makefile index 6aea26b..e137e08 100644 --- a/sbin/ipfw/Makefile +++ b/sbin/ipfw/Makefile @@ -3,7 +3,7 @@ .include <bsd.own.mk> PROG= ipfw -SRCS= ipfw2.c dummynet.c ipv6.c main.c nat.c +SRCS= ipfw2.c dummynet.c ipv6.c main.c nat.c context.c WARNS?= 2 .if ${MK_PF} != "no" diff --git a/sbin/ipfw/context.c b/sbin/ipfw/context.c new file mode 100644 index 0000000..bce576e --- /dev/null +++ b/sbin/ipfw/context.c @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2013 Ermal Lu‡i + * + * Redistribution and use in source forms, with and without modification, + * are permitted provided that this entire comment appears intact. + * + * Redistribution in binary form may occur without any restrictions. + * Obviously, it would be nice if you gave credit where credit is due + * but requiring it would be too onerous. + * + * This software is provided ``AS IS'' without any warranties of any kind. + * + * $FreeBSD$ + */ + +#include <sys/types.h> +#include <sys/socket.h> + +#include <net/if.h> +#include <net/if_var.h> + +#include <netinet/in.h> +#include <netinet/ip_fw.h> + +#include "ipfw2.h" + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <sysexits.h> +#include <string.h> +#include <errno.h> +#include <err.h> + +extern int ipfw_socket; + +int +ipfw_context_handler(int ac, char **av) +{ + ip_fw3_opheader *op3; + int error = 0; + uint32_t action = 0; + socklen_t len, nlen; + char *ifname; + + av++; + ac--; + NEED1("bad arguments, for usage summary ``ipfw''"); + + if (!strncmp(*av, "list", strlen(*av))) { + action = IP_FW_CTX_GET; + av++; + ac--; + if (ac > 0) + errx(EX_DATAERR, "list: does not take any extra arguments."); + + } else { + co.ctx = atoi(*av); + + av++; + ac--; + NEED1("bad arguments, for usage summary ``ipfw''"); + + if (!strncmp(*av, "create", strlen(*av))) + action = IP_FW_CTX_ADD; + else if (!strncmp(*av, "destroy", strlen(*av))) + action = IP_FW_CTX_DEL; + else { + if (!strncmp(*av, "madd", strlen(*av))) + action = IP_FW_CTX_ADDMEMBER; + else if (!strncmp(*av, "mdel", strlen(*av))) + action = IP_FW_CTX_DELMEMBER; + else + errx(EX_DATAERR, "Wrong parameters passed"); + + av++; + ac--; + NEED1("bad arguments, for usage summary ``ipfw''"); + + ifname = *av; + } + + ac--; + if (ac > 0) + errx(EX_DATAERR, "context handling: Too many arguments passed"); + + } + + if (co.test_only) + return (0); + + if (ipfw_socket < 0) + ipfw_socket = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); + if (ipfw_socket < 0) + err(EX_UNAVAILABLE, "socket"); + + switch (action) { + case IP_FW_CTX_ADD: + case IP_FW_CTX_DEL: + case IP_FW_CTX_SET: + len = sizeof(ip_fw3_opheader); + op3 = alloca(len); + /* Zero reserved fields */ + memset(op3, 0, sizeof(ip_fw3_opheader)); + op3->opcode = action; + op3->ctxid = co.ctx; + error = setsockopt(ipfw_socket, IPPROTO_IP, IP_FW3, op3, len); + break; + case IP_FW_CTX_ADDMEMBER: + case IP_FW_CTX_DELMEMBER: + len = sizeof(ip_fw3_opheader) + strlen(ifname) + 1; + op3 = alloca(len); + /* Zero reserved fields */ + memset(op3, 0, sizeof(ip_fw3_opheader) + strlen(ifname) + 1); + memcpy((op3 + 1), ifname, strlen(ifname)); + op3->opcode = action; + op3->ctxid = co.ctx; + error = setsockopt(ipfw_socket, IPPROTO_IP, IP_FW3, op3, len); + break; + case IP_FW_CTX_GET: + len = sizeof(ip_fw3_opheader) + 1000; + nlen = len; + do { + if (nlen > len) { + len = nlen; + } + op3 = alloca(len); + /* Zero reserved fields */ + memset(op3, 0, len); + op3->opcode = action; + op3->ctxid = co.ctx; + nlen = len; + error = getsockopt(ipfw_socket, IPPROTO_IP, IP_FW3, op3, &nlen); + } while (nlen > len && !error); + + if (!error) { + if (nlen == 0) + printf("There are no contexts defined\n"); + else + printf("Currently defined contexts and their members:\n%s\n", (char *)op3); + } else + err(EX_UNAVAILABLE, "Error returned: %s\n", strerror(error)); + + break; + } + + return (error); +} diff --git a/sbin/ipfw/ipfw2.c b/sbin/ipfw/ipfw2.c index 1d0d0ec..d20a4f6 100644 --- a/sbin/ipfw/ipfw2.c +++ b/sbin/ipfw/ipfw2.c @@ -54,7 +54,7 @@ #include <netinet/tcp.h> #include <arpa/inet.h> -struct cmdline_opts co; /* global options */ +struct cmdline_opts co = { 0 }; /* global options */ int resvd_set_number = RESVD_SET; @@ -422,6 +422,7 @@ safe_realloc(void *ptr, size_t size) int do_cmd(int optname, void *optval, uintptr_t optlen) { + ip_fw3_opheader op3; int i; if (co.test_only) @@ -432,6 +433,15 @@ do_cmd(int optname, void *optval, uintptr_t optlen) if (ipfw_socket < 0) err(EX_UNAVAILABLE, "socket"); + if (optname != IP_FW3 && optname != IP_DUMMYNET3 && optname != -IP_DUMMYNET3) { + memset(&op3, 0, sizeof op3); + op3.ctxid = co.ctx; + op3.opcode = IP_FW_CTX_SET; + i = setsockopt(ipfw_socket, IPPROTO_IP, IP_FW3, &op3, sizeof(op3)); + if (i) + errx(EX_OSERR, "setsockopt: choosing context"); + } + if (optname == IP_FW_GET || optname == IP_DUMMYNET_GET || optname == IP_FW_ADD || optname == IP_FW3 || optname == IP_FW_NAT_GET_CONFIG || @@ -477,6 +487,7 @@ do_setcmd3(int optname, void *optval, socklen_t optlen) memset(op3, 0, sizeof(ip_fw3_opheader)); memcpy(op3 + 1, optval, optlen); op3->opcode = optname; + op3->ctxid = co.ctx; return setsockopt(ipfw_socket, IPPROTO_IP, IP_FW3, op3, len); } @@ -4463,6 +4474,7 @@ table_list(uint16_t num, int need_header) a = (uint32_t *)(op3 + 1); *a = num; op3->opcode = IP_FW_TABLE_XGETSIZE; + op3->ctxid = co.ctx; if (do_cmd(IP_FW3, op3, (uintptr_t)&l) < 0) err(EX_OSERR, "getsockopt(IP_FW_TABLE_XGETSIZE)"); @@ -4473,6 +4485,7 @@ table_list(uint16_t num, int need_header) l = *a; tbl = safe_calloc(1, l); tbl->opheader.opcode = IP_FW_TABLE_XLIST; + tbl->opheader.ctxid = co.ctx; tbl->tbl = num; if (do_cmd(IP_FW3, tbl, (uintptr_t)&l) < 0) err(EX_OSERR, "getsockopt(IP_FW_TABLE_XLIST)"); diff --git a/sbin/ipfw/ipfw2.h b/sbin/ipfw/ipfw2.h index 6e895b8..3ef9b19 100644 --- a/sbin/ipfw/ipfw2.h +++ b/sbin/ipfw/ipfw2.h @@ -54,6 +54,7 @@ struct cmdline_opts { int use_set; /* work with specified set number */ /* 0 means all sets, otherwise apply to set use_set - 1 */ + u_int ctx; }; extern struct cmdline_opts co; @@ -282,6 +283,9 @@ void dummynet_list(int ac, char *av[], int show_counters); void dummynet_flush(void); int ipfw_delete_pipe(int pipe_or_queue, int n); +/* Contextes */ +int ipfw_context_handler(int, char **); + /* ipv6.c */ void print_unreach6_code(uint16_t code); void print_ip6(struct _ipfw_insn_ip6 *cmd, char const *s); diff --git a/sbin/ipfw/main.c b/sbin/ipfw/main.c index 82a299b..ab75a1b 100644 --- a/sbin/ipfw/main.c +++ b/sbin/ipfw/main.c @@ -262,7 +262,7 @@ ipfw_main(int oldac, char **oldav) save_av = av; optind = optreset = 1; /* restart getopt() */ - while ((ch = getopt(ac, av, "abcdefhinNp:qs:STtv")) != -1) + while ((ch = getopt(ac, av, "abcdefhinNp:qs:STtvx:")) != -1) switch (ch) { case 'a': do_acct = 1; @@ -335,6 +335,12 @@ ipfw_main(int oldac, char **oldav) co.verbose = 1; break; + case 'x': + co.ctx = atoi(optarg); + if (co.ctx == 0) + errx(EX_USAGE, "Context 0 is invalid"); + break; + default: free(save_av); return 1; @@ -362,7 +368,9 @@ ipfw_main(int oldac, char **oldav) co.do_nat = 0; co.do_pipe = 0; co.use_set = 0; - if (!strncmp(*av, "nat", strlen(*av))) + if (!strncmp(*av, "zone", strlen(*av))) + return (ipfw_context_handler(ac, av)); + else if (!strncmp(*av, "nat", strlen(*av))) co.do_nat = 1; else if (!strncmp(*av, "pipe", strlen(*av))) co.do_pipe = 1; @@ -389,6 +397,9 @@ ipfw_main(int oldac, char **oldav) } NEED1("missing command"); + if (!co.ctx && !co.do_pipe) + err(11, "Context is mandatory"); + /* * For pipes, queues and nats we normally say 'nat|pipe NN config' * but the code is easier to parse as 'nat|pipe config NN' @@ -458,7 +469,7 @@ ipfw_readfile(int ac, char *av[]) FILE *f = NULL; pid_t preproc = 0; - while ((c = getopt(ac, av, "cfNnp:qS")) != -1) { + while ((c = getopt(ac, av, "cfNnp:qSx:")) != -1) { switch(c) { case 'c': co.do_compact = 1; @@ -509,6 +520,12 @@ ipfw_readfile(int ac, char *av[]) co.show_sets = 1; break; + case 'x': + co.ctx = atoi(optarg); + if (co.ctx == 0) + errx(EX_USAGE, "Context 0 is invalid"); + break; + default: errx(EX_USAGE, "bad arguments, for usage" " summary ``ipfw''"); |