mirror of
https://github.com/opnsense/src.git
synced 2026-06-09 16:50:25 -04:00
Revert "tools: apply CP_multi_instance_ipfw.diff"
This reverts commit ddd376bb68.
Conflicts:
sys/netpfil/ipfw/ip_fw2.c
This commit is contained in:
parent
316b1f8425
commit
b62f18765f
11 changed files with 126 additions and 664 deletions
|
|
@ -1,7 +1,7 @@
|
|||
# $FreeBSD$
|
||||
|
||||
PROG= ipfw
|
||||
SRCS= ipfw2.c dummynet.c ipv6.c main.c nat.c altq.c context.c
|
||||
SRCS= ipfw2.c dummynet.c ipv6.c main.c nat.c altq.c
|
||||
WARNS?= 2
|
||||
DPADD= ${LIBUTIL}
|
||||
LDADD= -lutil
|
||||
|
|
|
|||
|
|
@ -1,148 +0,0 @@
|
|||
/*
|
||||
* 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));
|
||||
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, sizeof(ip_fw3_opheader));
|
||||
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 contextes defined\n");
|
||||
else
|
||||
printf("Currently defined contextes and their members:\n%s\n", (char *)op3);
|
||||
} else
|
||||
err(EX_UNAVAILABLE, "Error returned: %s\n", strerror(error));
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
|
@ -54,7 +54,7 @@
|
|||
#include <netinet/tcp.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
struct cmdline_opts co = { 0 }; /* global options */
|
||||
struct cmdline_opts co; /* global options */
|
||||
|
||||
int resvd_set_number = RESVD_SET;
|
||||
|
||||
|
|
@ -420,7 +420,6 @@ 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)
|
||||
|
|
@ -431,15 +430,6 @@ 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 ||
|
||||
|
|
@ -485,7 +475,6 @@ 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);
|
||||
}
|
||||
|
|
@ -4339,7 +4328,6 @@ 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)");
|
||||
|
||||
|
|
|
|||
|
|
@ -54,7 +54,6 @@ 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;
|
||||
|
|
@ -278,9 +277,6 @@ 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);
|
||||
|
|
|
|||
|
|
@ -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:STtvx:")) != -1)
|
||||
while ((ch = getopt(ac, av, "abcdefhinNp:qs:STtv")) != -1)
|
||||
switch (ch) {
|
||||
case 'a':
|
||||
do_acct = 1;
|
||||
|
|
@ -335,12 +335,6 @@ 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;
|
||||
|
|
@ -368,9 +362,7 @@ ipfw_main(int oldac, char **oldav)
|
|||
co.do_nat = 0;
|
||||
co.do_pipe = 0;
|
||||
co.use_set = 0;
|
||||
if (!strncmp(*av, "zone", strlen(*av)))
|
||||
return (ipfw_context_handler(ac, av));
|
||||
else if (!strncmp(*av, "nat", strlen(*av)))
|
||||
if (!strncmp(*av, "nat", strlen(*av)))
|
||||
co.do_nat = 1;
|
||||
else if (!strncmp(*av, "pipe", strlen(*av)))
|
||||
co.do_pipe = 1;
|
||||
|
|
@ -397,9 +389,6 @@ 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'
|
||||
|
|
@ -469,7 +458,7 @@ ipfw_readfile(int ac, char *av[])
|
|||
FILE *f = NULL;
|
||||
pid_t preproc = 0;
|
||||
|
||||
while ((c = getopt(ac, av, "cfNnp:qSx:")) != -1) {
|
||||
while ((c = getopt(ac, av, "cfNnp:qS")) != -1) {
|
||||
switch(c) {
|
||||
case 'c':
|
||||
co.do_compact = 1;
|
||||
|
|
@ -520,12 +509,6 @@ 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''");
|
||||
|
|
|
|||
|
|
@ -65,8 +65,7 @@
|
|||
/* IP_FW3 header/opcodes */
|
||||
typedef struct _ip_fw3_opheader {
|
||||
uint16_t opcode; /* Operation opcode */
|
||||
uint16_t ctxid;
|
||||
uint16_t reserved[2]; /* Align to 64-bit boundary */
|
||||
uint16_t reserved[3]; /* Align to 64-bit boundary */
|
||||
} ip_fw3_opheader;
|
||||
|
||||
|
||||
|
|
@ -77,12 +76,6 @@ typedef struct _ip_fw3_opheader {
|
|||
#define IP_FW_TABLE_XLIST 89 /* list table contents */
|
||||
#define IP_FW_TABLE_XLISTENTRY 90 /* list one table entry contents */
|
||||
#define IP_FW_TABLE_XZEROENTRY 91 /* zero one table entry stats */
|
||||
#define IP_FW_CTX_GET 92
|
||||
#define IP_FW_CTX_ADD 93
|
||||
#define IP_FW_CTX_DEL 94
|
||||
#define IP_FW_CTX_SET 95
|
||||
#define IP_FW_CTX_ADDMEMBER 96
|
||||
#define IP_FW_CTX_DELMEMBER 97
|
||||
|
||||
/*
|
||||
* The kernel representation of ipfw rules is made of a list of
|
||||
|
|
|
|||
|
|
@ -139,7 +139,8 @@ VNET_DEFINE(int, fw_verbose);
|
|||
VNET_DEFINE(u_int64_t, norule_counter);
|
||||
VNET_DEFINE(int, verbose_limit);
|
||||
|
||||
VNET_DEFINE(struct ip_fw_contextes, ip_fw_contexts);
|
||||
/* layer3_chain contains the list of rules for layer 3 */
|
||||
VNET_DEFINE(struct ip_fw_chain, layer3_chain);
|
||||
|
||||
VNET_DEFINE(int, ipfw_nat_ready) = 0;
|
||||
|
||||
|
|
@ -180,6 +181,9 @@ SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, default_to_accept, CTLFLAG_RDTUN,
|
|||
"Make the default rule accept all packets.");
|
||||
TUNABLE_INT("net.inet.ip.fw.default_to_accept", &default_to_accept);
|
||||
TUNABLE_INT("net.inet.ip.fw.tables_max", (int *)&default_fw_tables);
|
||||
SYSCTL_VNET_INT(_net_inet_ip_fw, OID_AUTO, static_count,
|
||||
CTLFLAG_RD, &VNET_NAME(layer3_chain.n_rules), 0,
|
||||
"Number of static rules");
|
||||
|
||||
#ifdef INET6
|
||||
SYSCTL_DECL(_net_inet6_ip6);
|
||||
|
|
@ -899,9 +903,6 @@ ipfw_chk(struct ip_fw_args *args)
|
|||
*/
|
||||
struct ifnet *oif = args->oif;
|
||||
|
||||
if (V_ip_fw_contexts.chain[oif->if_ispare[0]] == NULL)
|
||||
return (IP_FW_PASS);
|
||||
|
||||
int f_pos = 0; /* index of current rule in the array */
|
||||
int retval = 0;
|
||||
|
||||
|
|
@ -952,13 +953,7 @@ ipfw_chk(struct ip_fw_args *args)
|
|||
*/
|
||||
int dyn_dir = MATCH_UNKNOWN;
|
||||
ipfw_dyn_rule *q = NULL;
|
||||
|
||||
/* XXX: WARNING - The chain is accessed unlocked here.
|
||||
* There is a potential race here with context handling.
|
||||
* The chain pointer will get destroyed and a NULL
|
||||
* pointer dereference can happen!
|
||||
*/
|
||||
struct ip_fw_chain *chain = V_ip_fw_contexts.chain[oif->if_ispare[0]];
|
||||
struct ip_fw_chain *chain = &V_layer3_chain;
|
||||
|
||||
/*
|
||||
* We store in ulp a pointer to the upper layer protocol header.
|
||||
|
|
@ -2417,7 +2412,7 @@ do { \
|
|||
set_match(args, f_pos, chain);
|
||||
/* Check if this is 'global' nat rule */
|
||||
if (cmd->arg1 == 0) {
|
||||
retval = ipfw_nat_ptr(args, NULL, m, chain);
|
||||
retval = ipfw_nat_ptr(args, NULL, m);
|
||||
l = 0;
|
||||
done = 1;
|
||||
break;
|
||||
|
|
@ -2436,7 +2431,7 @@ do { \
|
|||
if (cmd->arg1 != IP_FW_TABLEARG)
|
||||
((ipfw_insn_nat *)cmd)->nat = t;
|
||||
}
|
||||
retval = ipfw_nat_ptr(args, t, m, chain);
|
||||
retval = ipfw_nat_ptr(args, t, m);
|
||||
}
|
||||
l = 0; /* exit inner loop */
|
||||
done = 1; /* exit outer loop */
|
||||
|
|
@ -2543,9 +2538,7 @@ sysctl_ipfw_table_num(SYSCTL_HANDLER_ARGS)
|
|||
if ((error != 0) || (req->newptr == NULL))
|
||||
return (error);
|
||||
|
||||
for (int i = 1; i < IP_FW_MAXCTX; i++)
|
||||
error += ipfw_resize_tables(V_ip_fw_contexts.chain[i], ntables);
|
||||
return (error);
|
||||
return (ipfw_resize_tables(&V_layer3_chain, ntables));
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
|
|
@ -2623,6 +2616,11 @@ ipfw_destroy(void)
|
|||
static int
|
||||
vnet_ipfw_init(const void *unused)
|
||||
{
|
||||
int error;
|
||||
struct ip_fw *rule = NULL;
|
||||
struct ip_fw_chain *chain;
|
||||
|
||||
chain = &V_layer3_chain;
|
||||
|
||||
/* First set up some values that are compile time options */
|
||||
V_autoinc_step = 100; /* bounded to 1..1000 in add_rule() */
|
||||
|
|
@ -2633,16 +2631,39 @@ vnet_ipfw_init(const void *unused)
|
|||
#ifdef IPFIREWALL_VERBOSE_LIMIT
|
||||
V_verbose_limit = IPFIREWALL_VERBOSE_LIMIT;
|
||||
#endif
|
||||
#ifdef IPFIREWALL_NAT
|
||||
LIST_INIT(&chain->nat);
|
||||
#endif
|
||||
|
||||
for (int i = 0; i < IP_FW_MAXCTX; i++)
|
||||
V_ip_fw_contexts.chain[i] = NULL;
|
||||
/* insert the default rule and create the initial map */
|
||||
chain->n_rules = 1;
|
||||
chain->static_len = sizeof(struct ip_fw);
|
||||
chain->map = malloc(sizeof(struct ip_fw *), M_IPFW, M_WAITOK | M_ZERO);
|
||||
if (chain->map)
|
||||
rule = malloc(chain->static_len, M_IPFW, M_WAITOK | M_ZERO);
|
||||
|
||||
IPFW_CTX_LOCK_INIT();
|
||||
/* Set initial number of tables */
|
||||
V_fw_tables_max = default_fw_tables;
|
||||
error = ipfw_init_tables(chain);
|
||||
if (error) {
|
||||
printf("ipfw2: setting up tables failed\n");
|
||||
free(chain->map, M_IPFW);
|
||||
free(rule, M_IPFW);
|
||||
return (ENOSPC);
|
||||
}
|
||||
|
||||
V_ip_fw_contexts.ifnet_arrival = EVENTHANDLER_REGISTER(ifnet_arrival_event,
|
||||
ipfw_attach_ifnet_event, NULL, EVENTHANDLER_PRI_ANY);
|
||||
/* fill and insert the default rule */
|
||||
rule->act_ofs = 0;
|
||||
rule->rulenum = IPFW_DEFAULT_RULE;
|
||||
rule->cmd_len = 1;
|
||||
rule->set = RESVD_SET;
|
||||
rule->cmd[0].len = 1;
|
||||
rule->cmd[0].opcode = default_to_accept ? O_ACCEPT : O_DENY;
|
||||
chain->rules = chain->default_rule = chain->map[0] = rule;
|
||||
chain->id = rule->id = 1;
|
||||
|
||||
ipfw_dyn_init();
|
||||
IPFW_LOCK_INIT(chain);
|
||||
ipfw_dyn_init(chain);
|
||||
|
||||
/* First set up some values that are compile time options */
|
||||
V_ipfw_vnet_ready = 1; /* Open for business */
|
||||
|
|
@ -2661,55 +2682,8 @@ vnet_ipfw_init(const void *unused)
|
|||
* is checked on each packet because there are no pfil hooks.
|
||||
*/
|
||||
V_ip_fw_ctl_ptr = ipfw_ctl;
|
||||
return ipfw_attach_hooks(1);
|
||||
}
|
||||
|
||||
int
|
||||
ipfw_context_init(int index)
|
||||
{
|
||||
struct ip_fw_chain *chain;
|
||||
struct ip_fw *rule = NULL;
|
||||
|
||||
if (index > IP_FW_MAXCTX)
|
||||
return (-1);
|
||||
|
||||
TAILQ_INIT(&V_ip_fw_contexts.iflist[index]);
|
||||
|
||||
chain = V_ip_fw_contexts.chain[index];
|
||||
|
||||
IPFW_LOCK_INIT(chain);
|
||||
|
||||
#ifdef IPFIREWALL_NAT
|
||||
LIST_INIT(&chain->nat);
|
||||
#endif
|
||||
/* insert the default rule and create the initial map */
|
||||
chain->n_rules = 1;
|
||||
chain->static_len = sizeof(struct ip_fw);
|
||||
chain->map = malloc(sizeof(struct ip_fw *), M_IPFW, M_WAITOK | M_ZERO);
|
||||
if (chain->map)
|
||||
rule = malloc(chain->static_len, M_IPFW, M_WAITOK | M_ZERO);
|
||||
|
||||
/* Set initial number of tables */
|
||||
V_fw_tables_max = default_fw_tables;
|
||||
ipfw_init_tables(chain);
|
||||
|
||||
/* fill and insert the default rule */
|
||||
rule->act_ofs = 0;
|
||||
rule->rulenum = IPFW_DEFAULT_RULE;
|
||||
rule->cmd_len = 1;
|
||||
rule->set = RESVD_SET;
|
||||
rule->cmd[0].len = 1;
|
||||
rule->cmd[0].opcode = default_to_accept ? O_ACCEPT : O_DENY;
|
||||
chain->rules = chain->default_rule = chain->map[0] = rule;
|
||||
chain->id = rule->id = 1;
|
||||
|
||||
/*
|
||||
* This can potentially be done on first dynamic rule
|
||||
* being added to chain.
|
||||
*/
|
||||
resize_dynamic_table(chain, V_curr_dyn_buckets);
|
||||
|
||||
return (0);
|
||||
error = ipfw_attach_hooks(1);
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -2718,9 +2692,11 @@ ipfw_context_init(int index)
|
|||
static int
|
||||
vnet_ipfw_uninit(const void *unused)
|
||||
{
|
||||
struct ip_fw *reap, *rule;
|
||||
struct ip_fw_chain *chain = &V_layer3_chain;
|
||||
int i;
|
||||
|
||||
V_ipfw_vnet_ready = 0; /* tell new callers to go away */
|
||||
|
||||
/*
|
||||
* disconnect from ipv4, ipv6, layer2 and sockopt.
|
||||
* Then grab, release and grab again the WLOCK so we make
|
||||
|
|
@ -2728,51 +2704,14 @@ vnet_ipfw_uninit(const void *unused)
|
|||
*/
|
||||
(void)ipfw_attach_hooks(0 /* detach */);
|
||||
V_ip_fw_ctl_ptr = NULL;
|
||||
|
||||
ipfw_dyn_uninit(0); /* run the callout_drain */
|
||||
|
||||
IPFW_CTX_WLOCK();
|
||||
EVENTHANDLER_DEREGISTER(ifnet_arrival_event, V_ip_fw_contexts.ifnet_arrival);
|
||||
for (int i = 0; i < IP_FW_MAXCTX; i++) {
|
||||
ipfw_context_uninit(i);
|
||||
}
|
||||
IPFW_CTX_WUNLOCK();
|
||||
IPFW_CTX_LOCK_DESTROY();
|
||||
|
||||
ipfw_dyn_uninit(1); /* free the remaining parts */
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
ipfw_context_uninit(int index)
|
||||
{
|
||||
struct ip_fw_chain *chain;
|
||||
struct ip_fw_ctx_iflist *ifl;
|
||||
struct ip_fw *reap, *rule;
|
||||
struct ifnet *ifp;
|
||||
int i;
|
||||
|
||||
if (index > IP_FW_MAXCTX)
|
||||
return (-1);
|
||||
|
||||
chain = V_ip_fw_contexts.chain[index];
|
||||
if (chain == NULL)
|
||||
return (0);
|
||||
|
||||
while (!TAILQ_EMPTY(&V_ip_fw_contexts.iflist[index])) {
|
||||
ifl = TAILQ_FIRST(&V_ip_fw_contexts.iflist[index]);
|
||||
TAILQ_REMOVE(&V_ip_fw_contexts.iflist[index], ifl, entry);
|
||||
ifp = ifunit(ifl->ifname);
|
||||
if (ifp != NULL)
|
||||
ifp->if_ispare[0] = 0;
|
||||
free(ifl, M_IPFW);
|
||||
}
|
||||
|
||||
IPFW_UH_WLOCK(chain);
|
||||
IPFW_UH_WUNLOCK(chain);
|
||||
IPFW_UH_WLOCK(chain);
|
||||
|
||||
IPFW_WLOCK(chain);
|
||||
ipfw_dyn_uninit(0); /* run the callout_drain */
|
||||
IPFW_WUNLOCK(chain);
|
||||
|
||||
ipfw_destroy_tables(chain);
|
||||
reap = NULL;
|
||||
IPFW_WLOCK(chain);
|
||||
|
|
@ -2788,10 +2727,8 @@ ipfw_context_uninit(int index)
|
|||
if (reap != NULL)
|
||||
ipfw_reap_rules(reap);
|
||||
IPFW_LOCK_DESTROY(chain);
|
||||
|
||||
free(chain, M_IPFW);
|
||||
|
||||
return (0);
|
||||
ipfw_dyn_uninit(1); /* free the remaining parts */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -121,9 +121,11 @@ struct ipfw_dyn_bucket {
|
|||
*/
|
||||
static VNET_DEFINE(struct ipfw_dyn_bucket *, ipfw_dyn_v);
|
||||
static VNET_DEFINE(u_int32_t, dyn_buckets_max);
|
||||
static VNET_DEFINE(u_int32_t, curr_dyn_buckets);
|
||||
static VNET_DEFINE(struct callout, ipfw_timeout);
|
||||
#define V_ipfw_dyn_v VNET(ipfw_dyn_v)
|
||||
#define V_dyn_buckets_max VNET(dyn_buckets_max)
|
||||
#define V_curr_dyn_buckets VNET(curr_dyn_buckets)
|
||||
#define V_ipfw_timeout VNET(ipfw_timeout)
|
||||
|
||||
static VNET_DEFINE(uma_zone_t, ipfw_dyn_rule_zone);
|
||||
|
|
@ -179,8 +181,6 @@ static VNET_DEFINE(u_int32_t, dyn_max); /* max # of dynamic rules */
|
|||
|
||||
static int last_log; /* Log ratelimiting */
|
||||
|
||||
VNET_DEFINE(u_int32_t, curr_dyn_buckets);
|
||||
|
||||
static void ipfw_dyn_tick(void *vnetx);
|
||||
static void check_dyn_rules(struct ip_fw_chain *, struct ip_fw *,
|
||||
int, int, int);
|
||||
|
|
@ -470,7 +470,7 @@ ipfw_dyn_unlock(ipfw_dyn_rule *q)
|
|||
IPFW_BUCK_UNLOCK(q->bucket);
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
resize_dynamic_table(struct ip_fw_chain *chain, int nbuckets)
|
||||
{
|
||||
int i, k, nbuckets_old;
|
||||
|
|
@ -970,6 +970,7 @@ ipfw_dyn_send_ka(struct mbuf **mtailp, ipfw_dyn_rule *q)
|
|||
static void
|
||||
ipfw_dyn_tick(void * vnetx)
|
||||
{
|
||||
struct ip_fw_chain *chain;
|
||||
int check_ka = 0;
|
||||
#ifdef VIMAGE
|
||||
struct vnet *vp = vnetx;
|
||||
|
|
@ -977,6 +978,7 @@ ipfw_dyn_tick(void * vnetx)
|
|||
|
||||
CURVNET_SET(vp);
|
||||
|
||||
chain = &V_layer3_chain;
|
||||
|
||||
/* Run keepalive checks every keepalive_period iff ka is enabled */
|
||||
if ((V_dyn_keepalive_last + V_dyn_keepalive_period <= time_uptime) &&
|
||||
|
|
@ -985,12 +987,7 @@ ipfw_dyn_tick(void * vnetx)
|
|||
check_ka = 1;
|
||||
}
|
||||
|
||||
IPFW_CTX_RLOCK();
|
||||
for (int i = 1; i < IP_FW_MAXCTX; i++) {
|
||||
if (V_ip_fw_contexts.chain[i] != NULL)
|
||||
check_dyn_rules(V_ip_fw_contexts.chain[i], NULL, RESVD_SET, check_ka, 1);
|
||||
}
|
||||
IPFW_CTX_RUNLOCK();
|
||||
check_dyn_rules(chain, NULL, RESVD_SET, check_ka, 1);
|
||||
|
||||
callout_reset_on(&V_ipfw_timeout, hz, ipfw_dyn_tick, vnetx, 0);
|
||||
|
||||
|
|
@ -1306,7 +1303,7 @@ ipfw_expire_dyn_rules(struct ip_fw_chain *chain, struct ip_fw *rule, int set)
|
|||
}
|
||||
|
||||
void
|
||||
ipfw_dyn_init()
|
||||
ipfw_dyn_init(struct ip_fw_chain *chain)
|
||||
{
|
||||
|
||||
V_ipfw_dyn_v = NULL;
|
||||
|
|
@ -1335,6 +1332,12 @@ ipfw_dyn_init()
|
|||
uma_zone_set_max(V_ipfw_dyn_rule_zone, V_dyn_max);
|
||||
|
||||
callout_init(&V_ipfw_timeout, CALLOUT_MPSAFE);
|
||||
|
||||
/*
|
||||
* This can potentially be done on first dynamic rule
|
||||
* being added to chain.
|
||||
*/
|
||||
resize_dynamic_table(chain, V_curr_dyn_buckets);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -64,33 +64,26 @@ ifaddr_change(void *arg __unused, struct ifnet *ifp)
|
|||
|
||||
KASSERT(curvnet == ifp->if_vnet,
|
||||
("curvnet(%p) differs from iface vnet(%p)", curvnet, ifp->if_vnet));
|
||||
|
||||
IPFW_CTX_RLOCK();
|
||||
for (int i = 1; i < IP_FW_MAXCTX; i++) {
|
||||
chain = V_ip_fw_contexts.chain[i];
|
||||
if (chain == NULL)
|
||||
chain = &V_layer3_chain;
|
||||
IPFW_WLOCK(chain);
|
||||
/* Check every nat entry... */
|
||||
LIST_FOREACH(ptr, &chain->nat, _next) {
|
||||
/* ...using nic 'ifp->if_xname' as dynamic alias address. */
|
||||
if (strncmp(ptr->if_name, ifp->if_xname, IF_NAMESIZE) != 0)
|
||||
continue;
|
||||
IPFW_WLOCK(chain);
|
||||
/* Check every nat entry... */
|
||||
LIST_FOREACH(ptr, &chain->nat, _next) {
|
||||
/* ...using nic 'ifp->if_xname' as dynamic alias address. */
|
||||
if (strncmp(ptr->if_name, ifp->if_xname, IF_NAMESIZE) != 0)
|
||||
if_addr_rlock(ifp);
|
||||
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
|
||||
if (ifa->ifa_addr == NULL)
|
||||
continue;
|
||||
if_addr_rlock(ifp);
|
||||
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
|
||||
if (ifa->ifa_addr == NULL)
|
||||
continue;
|
||||
if (ifa->ifa_addr->sa_family != AF_INET)
|
||||
continue;
|
||||
ptr->ip = ((struct sockaddr_in *)
|
||||
(ifa->ifa_addr))->sin_addr;
|
||||
LibAliasSetAddress(ptr->lib, ptr->ip);
|
||||
}
|
||||
if_addr_runlock(ifp);
|
||||
if (ifa->ifa_addr->sa_family != AF_INET)
|
||||
continue;
|
||||
ptr->ip = ((struct sockaddr_in *)
|
||||
(ifa->ifa_addr))->sin_addr;
|
||||
LibAliasSetAddress(ptr->lib, ptr->ip);
|
||||
}
|
||||
IPFW_WUNLOCK(chain);
|
||||
if_addr_runlock(ifp);
|
||||
}
|
||||
IPFW_CTX_RUNLOCK();
|
||||
IPFW_WUNLOCK(chain);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -213,18 +206,18 @@ add_redir_spool_cfg(char *buf, struct cfg_nat *ptr)
|
|||
/*
|
||||
* ipfw_nat - perform mbuf header translation.
|
||||
*
|
||||
* Note *chain has to be locked while calling ipfw_nat() in
|
||||
* Note V_layer3_chain has to be locked while calling ipfw_nat() in
|
||||
* 'global' operation mode (t == NULL).
|
||||
*
|
||||
*/
|
||||
static int
|
||||
ipfw_nat(struct ip_fw_args *args, struct cfg_nat *t, struct mbuf *m,
|
||||
struct ip_fw_chain *chain)
|
||||
ipfw_nat(struct ip_fw_args *args, struct cfg_nat *t, struct mbuf *m)
|
||||
{
|
||||
struct mbuf *mcl;
|
||||
struct ip *ip;
|
||||
/* XXX - libalias duct tape */
|
||||
int ldt, retval, found;
|
||||
struct ip_fw_chain *chain;
|
||||
char *c;
|
||||
|
||||
ldt = 0;
|
||||
|
|
@ -283,6 +276,7 @@ ipfw_nat(struct ip_fw_args *args, struct cfg_nat *t, struct mbuf *m,
|
|||
}
|
||||
|
||||
found = 0;
|
||||
chain = &V_layer3_chain;
|
||||
IPFW_RLOCK_ASSERT(chain);
|
||||
/* Check every nat entry... */
|
||||
LIST_FOREACH(t, &chain->nat, _next) {
|
||||
|
|
@ -397,10 +391,11 @@ lookup_nat(struct nat_list *l, int nat_id)
|
|||
}
|
||||
|
||||
static int
|
||||
ipfw_nat_cfg(struct sockopt *sopt, struct ip_fw_chain *chain)
|
||||
ipfw_nat_cfg(struct sockopt *sopt)
|
||||
{
|
||||
struct cfg_nat *cfg, *ptr;
|
||||
char *buf;
|
||||
struct ip_fw_chain *chain = &V_layer3_chain;
|
||||
size_t len;
|
||||
int gencnt, error = 0;
|
||||
|
||||
|
|
@ -473,9 +468,10 @@ out:
|
|||
}
|
||||
|
||||
static int
|
||||
ipfw_nat_del(struct sockopt *sopt, struct ip_fw_chain *chain)
|
||||
ipfw_nat_del(struct sockopt *sopt)
|
||||
{
|
||||
struct cfg_nat *ptr;
|
||||
struct ip_fw_chain *chain = &V_layer3_chain;
|
||||
int i;
|
||||
|
||||
sooptcopyin(sopt, &i, sizeof i, sizeof i);
|
||||
|
|
@ -496,8 +492,9 @@ ipfw_nat_del(struct sockopt *sopt, struct ip_fw_chain *chain)
|
|||
}
|
||||
|
||||
static int
|
||||
ipfw_nat_get_cfg(struct sockopt *sopt, struct ip_fw_chain *chain)
|
||||
ipfw_nat_get_cfg(struct sockopt *sopt)
|
||||
{
|
||||
struct ip_fw_chain *chain = &V_layer3_chain;
|
||||
struct cfg_nat *n;
|
||||
struct cfg_redir *r;
|
||||
struct cfg_spool *s;
|
||||
|
|
@ -555,11 +552,14 @@ retry:
|
|||
}
|
||||
|
||||
static int
|
||||
ipfw_nat_get_log(struct sockopt *sopt, struct ip_fw_chain *chain)
|
||||
ipfw_nat_get_log(struct sockopt *sopt)
|
||||
{
|
||||
uint8_t *data;
|
||||
struct cfg_nat *ptr;
|
||||
int i, size;
|
||||
struct ip_fw_chain *chain;
|
||||
|
||||
chain = &V_layer3_chain;
|
||||
|
||||
IPFW_RLOCK(chain);
|
||||
/* one pass to count, one to copy the data */
|
||||
|
|
@ -604,22 +604,17 @@ vnet_ipfw_nat_uninit(const void *arg __unused)
|
|||
struct cfg_nat *ptr, *ptr_temp;
|
||||
struct ip_fw_chain *chain;
|
||||
|
||||
IPFW_CTX_RLOCK();
|
||||
for (int i = 1; i < IP_FW_MAXCTX; i++) {
|
||||
chain = V_ip_fw_contexts.chain[i];
|
||||
IPFW_WLOCK(chain);
|
||||
LIST_FOREACH_SAFE(ptr, &chain->nat, _next, ptr_temp) {
|
||||
LIST_REMOVE(ptr, _next);
|
||||
del_redir_spool_cfg(ptr, &ptr->redir_chain);
|
||||
LibAliasUninit(ptr->lib);
|
||||
free(ptr, M_IPFW);
|
||||
}
|
||||
flush_nat_ptrs(chain, -1 /* flush all */);
|
||||
V_ipfw_nat_ready = 0;
|
||||
IPFW_WUNLOCK(chain);
|
||||
chain = &V_layer3_chain;
|
||||
IPFW_WLOCK(chain);
|
||||
LIST_FOREACH_SAFE(ptr, &chain->nat, _next, ptr_temp) {
|
||||
LIST_REMOVE(ptr, _next);
|
||||
del_redir_spool_cfg(ptr, &ptr->redir_chain);
|
||||
LibAliasUninit(ptr->lib);
|
||||
free(ptr, M_IPFW);
|
||||
}
|
||||
IPFW_CTX_RUNLOCK();
|
||||
|
||||
flush_nat_ptrs(chain, -1 /* flush all */);
|
||||
V_ipfw_nat_ready = 0;
|
||||
IPFW_WUNLOCK(chain);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -170,9 +170,6 @@ enum { /* result for matching dynamic rules */
|
|||
MATCH_UNKNOWN,
|
||||
};
|
||||
|
||||
VNET_DECLARE(u_int32_t, curr_dyn_buckets);
|
||||
#define V_curr_dyn_buckets VNET(curr_dyn_buckets)
|
||||
|
||||
/*
|
||||
* The lock for dynamic rules is only used once outside the file,
|
||||
* and only to release the result of lookup_dyn_rule().
|
||||
|
|
@ -181,7 +178,6 @@ VNET_DECLARE(u_int32_t, curr_dyn_buckets);
|
|||
struct ip_fw_chain;
|
||||
void ipfw_expire_dyn_rules(struct ip_fw_chain *, struct ip_fw *, int);
|
||||
void ipfw_dyn_unlock(ipfw_dyn_rule *q);
|
||||
int resize_dynamic_table(struct ip_fw_chain *, int);
|
||||
|
||||
struct tcphdr;
|
||||
struct mbuf *ipfw_send_pkt(struct mbuf *, struct ipfw_flow_id *,
|
||||
|
|
@ -193,7 +189,7 @@ ipfw_dyn_rule *ipfw_lookup_dyn_rule(struct ipfw_flow_id *pkt,
|
|||
void ipfw_remove_dyn_children(struct ip_fw *rule);
|
||||
void ipfw_get_dynamic(struct ip_fw_chain *chain, char **bp, const char *ep);
|
||||
|
||||
void ipfw_dyn_init(void); /* per-vnet initialization */
|
||||
void ipfw_dyn_init(struct ip_fw_chain *); /* per-vnet initialization */
|
||||
void ipfw_dyn_uninit(int); /* per-vnet deinitialization */
|
||||
int ipfw_dyn_len(void);
|
||||
|
||||
|
|
@ -204,6 +200,9 @@ VNET_DECLARE(int, fw_one_pass);
|
|||
VNET_DECLARE(int, fw_verbose);
|
||||
#define V_fw_verbose VNET(fw_verbose)
|
||||
|
||||
VNET_DECLARE(struct ip_fw_chain, layer3_chain);
|
||||
#define V_layer3_chain VNET(layer3_chain)
|
||||
|
||||
VNET_DECLARE(u_int32_t, set_disable);
|
||||
#define V_set_disable VNET(set_disable)
|
||||
|
||||
|
|
@ -235,33 +234,6 @@ struct ip_fw_chain {
|
|||
uint32_t gencnt; /* generation count */
|
||||
};
|
||||
|
||||
struct ip_fw_ctx_iflist {
|
||||
TAILQ_ENTRY(ip_fw_ctx_iflist) entry;
|
||||
char ifname[IFNAMSIZ];
|
||||
};
|
||||
|
||||
#define IP_FW_MAXCTX 4096
|
||||
struct ip_fw_contextes {
|
||||
struct ip_fw_chain *chain[IP_FW_MAXCTX]; /* Arrays of contextes */
|
||||
TAILQ_HEAD(, ip_fw_ctx_iflist) iflist[IP_FW_MAXCTX];
|
||||
struct rwlock rwctx;
|
||||
eventhandler_tag ifnet_arrival;
|
||||
};
|
||||
|
||||
VNET_DECLARE(struct ip_fw_contextes, ip_fw_contexts);
|
||||
#define V_ip_fw_contexts VNET(ip_fw_contexts)
|
||||
|
||||
#define IPFW_CTX_LOCK_INIT() rw_init(&V_ip_fw_contexts.rwctx, "IPFW context")
|
||||
#define IPFW_CTX_LOCK_DESTROY() rw_destroy(&V_ip_fw_contexts.rwctx)
|
||||
#define IPFW_CTX_WLOCK() rw_wlock(&V_ip_fw_contexts.rwctx)
|
||||
#define IPFW_CTX_WUNLOCK() rw_wunlock(&V_ip_fw_contexts.rwctx)
|
||||
#define IPFW_CTX_RLOCK() rw_rlock(&V_ip_fw_contexts.rwctx)
|
||||
#define IPFW_CTX_RUNLOCK() rw_runlock(&V_ip_fw_contexts.rwctx)
|
||||
|
||||
void ipfw_attach_ifnet_event(void *, struct ifnet *);
|
||||
int ipfw_context_init(int);
|
||||
int ipfw_context_uninit(int);
|
||||
|
||||
struct sockopt; /* used by tcp_var.h */
|
||||
|
||||
/* Macro for working with various counters */
|
||||
|
|
@ -352,9 +324,8 @@ int ipfw_resize_tables(struct ip_fw_chain *ch, unsigned int ntables);
|
|||
|
||||
extern struct cfg_nat *(*lookup_nat_ptr)(struct nat_list *, int);
|
||||
|
||||
typedef int ipfw_nat_t(struct ip_fw_args *, struct cfg_nat *, struct mbuf *,
|
||||
struct ip_fw_chain *);
|
||||
typedef int ipfw_nat_cfg_t(struct sockopt *, struct ip_fw_chain *);
|
||||
typedef int ipfw_nat_t(struct ip_fw_args *, struct cfg_nat *, struct mbuf *);
|
||||
typedef int ipfw_nat_cfg_t(struct sockopt *);
|
||||
|
||||
VNET_DECLARE(int, ipfw_nat_ready);
|
||||
#define V_ipfw_nat_ready VNET(ipfw_nat_ready)
|
||||
|
|
|
|||
|
|
@ -943,15 +943,12 @@ ipfw_ctl(struct sockopt *sopt)
|
|||
#define RULE_MAXSIZE (256*sizeof(u_int32_t))
|
||||
int error;
|
||||
size_t size, len, valsize;
|
||||
struct ifnet *ifp;
|
||||
struct ip_fw *buf, *rule;
|
||||
static struct ip_fw_chain *chain;
|
||||
struct ip_fw_ctx_iflist *tmpifl, *tmpifl2;
|
||||
ip_fw3_opheader *op3 = NULL;
|
||||
struct ip_fw_chain *chain;
|
||||
u_int32_t rulenum[2];
|
||||
uint32_t opt;
|
||||
char xbuf[128];
|
||||
char *ifname;
|
||||
ip_fw3_opheader *op3 = NULL;
|
||||
|
||||
error = priv_check(sopt->sopt_td, PRIV_NETINET_IPFW);
|
||||
if (error)
|
||||
|
|
@ -968,6 +965,7 @@ ipfw_ctl(struct sockopt *sopt)
|
|||
return (error);
|
||||
}
|
||||
|
||||
chain = &V_layer3_chain;
|
||||
error = 0;
|
||||
|
||||
/* Save original valsize before it is altered via sooptcopyin() */
|
||||
|
|
@ -982,236 +980,9 @@ ipfw_ctl(struct sockopt *sopt)
|
|||
return (error);
|
||||
op3 = (ip_fw3_opheader *)xbuf;
|
||||
opt = op3->opcode;
|
||||
|
||||
if (op3->ctxid > IP_FW_MAXCTX)
|
||||
return (EINVAL);
|
||||
|
||||
if (opt != IP_FW_CTX_GET) {
|
||||
if (opt != IP_FW_CTX_ADD) {
|
||||
if (op3->ctxid == 0)
|
||||
return (ENOENT);
|
||||
}
|
||||
|
||||
chain = V_ip_fw_contexts.chain[op3->ctxid];
|
||||
}
|
||||
}
|
||||
|
||||
/* Verification needed to avoid problems */
|
||||
switch (opt) {
|
||||
case IP_FW_CTX_GET:
|
||||
case IP_FW_CTX_ADD:
|
||||
case IP_FW_CTX_DEL:
|
||||
break;
|
||||
default:
|
||||
if (chain == NULL)
|
||||
return (EINVAL);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
switch (opt) {
|
||||
case IP_FW_CTX_ADD:
|
||||
IPFW_CTX_WLOCK();
|
||||
if (V_ip_fw_contexts.chain[op3->ctxid] != NULL) {
|
||||
IPFW_CTX_WUNLOCK();
|
||||
return (EEXIST);
|
||||
}
|
||||
|
||||
chain = malloc(sizeof(struct ip_fw_chain), M_IPFW, M_WAITOK | M_ZERO);
|
||||
TAILQ_INIT(&V_ip_fw_contexts.iflist[op3->ctxid]);
|
||||
V_ip_fw_contexts.chain[op3->ctxid] = chain;
|
||||
ipfw_context_init(op3->ctxid); /* XXX: error checking */
|
||||
IPFW_CTX_WUNLOCK();
|
||||
break;
|
||||
|
||||
case IP_FW_CTX_DEL:
|
||||
IPFW_CTX_WLOCK();
|
||||
if (V_ip_fw_contexts.chain[op3->ctxid] == NULL) {
|
||||
IPFW_CTX_WUNLOCK();
|
||||
return (ENOENT);
|
||||
}
|
||||
|
||||
ipfw_context_uninit(op3->ctxid);
|
||||
V_ip_fw_contexts.chain[op3->ctxid] = NULL;
|
||||
IPFW_CTX_WUNLOCK();
|
||||
break;
|
||||
|
||||
case IP_FW_CTX_GET:
|
||||
{
|
||||
int i, n, len = 0, want;
|
||||
char *bufout, *tmpbuf;
|
||||
|
||||
sopt->sopt_valsize = valsize;
|
||||
|
||||
IPFW_CTX_RLOCK();
|
||||
for (i = 1; i < IP_FW_MAXCTX; i++) {
|
||||
if (op3->ctxid > 0 && op3->ctxid != i)
|
||||
continue;
|
||||
if (op3->ctxid > 0 && op3->ctxid < i)
|
||||
break;
|
||||
|
||||
if (V_ip_fw_contexts.chain[i] == NULL)
|
||||
continue;
|
||||
|
||||
/* Calculate number of bytes for the integer */
|
||||
n = i;
|
||||
while (n > 0) {
|
||||
n /= 10;
|
||||
len++;
|
||||
}
|
||||
TAILQ_FOREACH(tmpifl, &V_ip_fw_contexts.iflist[i], entry) {
|
||||
len += strlen(tmpifl->ifname) + 1;
|
||||
}
|
||||
len += 3; // newline, :, space
|
||||
}
|
||||
IPFW_CTX_RUNLOCK();
|
||||
|
||||
if (len > sopt->sopt_valsize) {
|
||||
sopt->sopt_valsize = len;
|
||||
break;
|
||||
}
|
||||
|
||||
bufout = malloc(len, M_TEMP, M_WAITOK | M_ZERO);
|
||||
if (bufout == NULL)
|
||||
break;
|
||||
|
||||
/* Record our size for later checks */
|
||||
want = len;
|
||||
len = 0;
|
||||
IPFW_CTX_RLOCK();
|
||||
/* Recalculate length to detect if smth changed */
|
||||
for (i = 1; i < IP_FW_MAXCTX; i++) {
|
||||
if (op3->ctxid > 0 && op3->ctxid != i)
|
||||
continue;
|
||||
if (op3->ctxid > 0 && op3->ctxid < i)
|
||||
break;
|
||||
|
||||
if (V_ip_fw_contexts.chain[i] == NULL)
|
||||
continue;
|
||||
|
||||
/* Calculate number of bytes for the integer */
|
||||
n = i;
|
||||
while (n > 0) {
|
||||
n /= 10;
|
||||
len++;
|
||||
}
|
||||
TAILQ_FOREACH(tmpifl, &V_ip_fw_contexts.iflist[i], entry) {
|
||||
len += strlen(tmpifl->ifname) + 1;
|
||||
}
|
||||
len += 3; // newline, :, space
|
||||
}
|
||||
|
||||
if (want >= len) {
|
||||
tmpbuf = bufout;
|
||||
for (i = 1; i < IP_FW_MAXCTX; i++) {
|
||||
if (op3->ctxid > 0 && op3->ctxid != i)
|
||||
continue;
|
||||
if (op3->ctxid > 0 && op3->ctxid < i)
|
||||
break;
|
||||
|
||||
if (V_ip_fw_contexts.chain[i] == NULL)
|
||||
continue;
|
||||
|
||||
sprintf(tmpbuf, "%d: ", i);
|
||||
tmpbuf += strlen(tmpbuf);
|
||||
TAILQ_FOREACH(tmpifl, &V_ip_fw_contexts.iflist[i], entry) {
|
||||
sprintf(tmpbuf, "%s,", tmpifl->ifname);
|
||||
tmpbuf += strlen(tmpifl->ifname) + 1;
|
||||
}
|
||||
sprintf(tmpbuf, "\n");
|
||||
tmpbuf++;
|
||||
}
|
||||
}
|
||||
IPFW_CTX_RUNLOCK();
|
||||
|
||||
if (want >= len)
|
||||
error = sooptcopyout(sopt, bufout, len);
|
||||
else
|
||||
len = 0;
|
||||
free(bufout, M_TEMP);
|
||||
}
|
||||
break;
|
||||
|
||||
case IP_FW_CTX_SET:
|
||||
/* XXX: Maybe not use this option at all? */
|
||||
IPFW_CTX_RLOCK();
|
||||
if (V_ip_fw_contexts.chain[op3->ctxid] == NULL)
|
||||
error = ENOENT;
|
||||
else
|
||||
chain = V_ip_fw_contexts.chain[op3->ctxid];
|
||||
IPFW_CTX_RUNLOCK();
|
||||
break;
|
||||
|
||||
case IP_FW_CTX_ADDMEMBER:
|
||||
{
|
||||
int i;
|
||||
|
||||
ifname = (char *)(op3 + 1);
|
||||
ifp = ifunit(ifname);
|
||||
if (ifp == NULL)
|
||||
return (ENOENT);
|
||||
|
||||
tmpifl = malloc(sizeof(*tmpifl), M_IPFW, M_WAITOK | M_ZERO);
|
||||
|
||||
IPFW_CTX_WLOCK();
|
||||
if (V_ip_fw_contexts.chain[op3->ctxid] == NULL) {
|
||||
IPFW_CTX_WUNLOCK();
|
||||
free(tmpifl, M_IPFW);
|
||||
return (ENOENT);
|
||||
}
|
||||
|
||||
for (i = 1; i < IP_FW_MAXCTX; i++) {
|
||||
if (V_ip_fw_contexts.chain[i] == NULL)
|
||||
continue;
|
||||
|
||||
TAILQ_FOREACH(tmpifl2, &V_ip_fw_contexts.iflist[i], entry) {
|
||||
if (strlen(tmpifl2->ifname) != strlen(ifname))
|
||||
continue;
|
||||
if (!strcmp(tmpifl2->ifname, ifname))
|
||||
goto ctxifacefound;
|
||||
}
|
||||
}
|
||||
ctxifacefound:
|
||||
if (tmpifl2 != NULL) {
|
||||
IPFW_CTX_WUNLOCK();
|
||||
free(tmpifl, M_IPFW);
|
||||
return (EEXIST);
|
||||
}
|
||||
|
||||
strlcpy(tmpifl->ifname, ifname, IFNAMSIZ);
|
||||
TAILQ_INSERT_HEAD(&V_ip_fw_contexts.iflist[op3->ctxid], tmpifl, entry);
|
||||
ifp->if_ispare[0] = op3->ctxid;
|
||||
IPFW_CTX_WUNLOCK();
|
||||
}
|
||||
break;
|
||||
|
||||
case IP_FW_CTX_DELMEMBER:
|
||||
IPFW_CTX_WLOCK();
|
||||
if (V_ip_fw_contexts.chain[op3->ctxid] == NULL) {
|
||||
IPFW_CTX_WUNLOCK();
|
||||
return (ENOENT);
|
||||
}
|
||||
|
||||
ifname = (char *)(op3 + 1);
|
||||
TAILQ_FOREACH(tmpifl2, &V_ip_fw_contexts.iflist[op3->ctxid], entry) {
|
||||
if (strlen(tmpifl2->ifname) != strlen(ifname))
|
||||
continue;
|
||||
if (!strcmp(tmpifl2->ifname, ifname))
|
||||
break;
|
||||
}
|
||||
if (tmpifl2 == NULL) {
|
||||
IPFW_CTX_WUNLOCK();
|
||||
return (ENOENT);
|
||||
}
|
||||
|
||||
TAILQ_REMOVE(&V_ip_fw_contexts.iflist[op3->ctxid], tmpifl2, entry);
|
||||
IPFW_CTX_WUNLOCK();
|
||||
free(tmpifl2, M_IPFW);
|
||||
|
||||
ifp = ifunit(ifname);
|
||||
if (ifp != NULL)
|
||||
ifp->if_ispare[0] = 0;
|
||||
break;
|
||||
|
||||
case IP_FW_GET:
|
||||
/*
|
||||
* pass up a copy of the current rules. Static rules
|
||||
|
|
@ -1509,7 +1280,7 @@ ctxifacefound:
|
|||
/*--- NAT operations are protected by the IPFW_LOCK ---*/
|
||||
case IP_FW_NAT_CFG:
|
||||
if (IPFW_NAT_LOADED)
|
||||
error = ipfw_nat_cfg_ptr(sopt, chain);
|
||||
error = ipfw_nat_cfg_ptr(sopt);
|
||||
else {
|
||||
printf("IP_FW_NAT_CFG: %s\n",
|
||||
"ipfw_nat not present, please load it");
|
||||
|
|
@ -1519,7 +1290,7 @@ ctxifacefound:
|
|||
|
||||
case IP_FW_NAT_DEL:
|
||||
if (IPFW_NAT_LOADED)
|
||||
error = ipfw_nat_del_ptr(sopt, chain);
|
||||
error = ipfw_nat_del_ptr(sopt);
|
||||
else {
|
||||
printf("IP_FW_NAT_DEL: %s\n",
|
||||
"ipfw_nat not present, please load it");
|
||||
|
|
@ -1529,7 +1300,7 @@ ctxifacefound:
|
|||
|
||||
case IP_FW_NAT_GET_CONFIG:
|
||||
if (IPFW_NAT_LOADED)
|
||||
error = ipfw_nat_get_cfg_ptr(sopt, chain);
|
||||
error = ipfw_nat_get_cfg_ptr(sopt);
|
||||
else {
|
||||
printf("IP_FW_NAT_GET_CFG: %s\n",
|
||||
"ipfw_nat not present, please load it");
|
||||
|
|
@ -1539,7 +1310,7 @@ ctxifacefound:
|
|||
|
||||
case IP_FW_NAT_GET_LOG:
|
||||
if (IPFW_NAT_LOADED)
|
||||
error = ipfw_nat_get_log_ptr(sopt, chain);
|
||||
error = ipfw_nat_get_log_ptr(sopt);
|
||||
else {
|
||||
printf("IP_FW_NAT_GET_LOG: %s\n",
|
||||
"ipfw_nat not present, please load it");
|
||||
|
|
@ -1556,33 +1327,6 @@ ctxifacefound:
|
|||
#undef RULE_MAXSIZE
|
||||
}
|
||||
|
||||
void
|
||||
ipfw_attach_ifnet_event(void *arg __unused, struct ifnet *ifp)
|
||||
{
|
||||
struct ip_fw_ctx_iflist *tmpifl;
|
||||
|
||||
CURVNET_SET(ifp->if_vnet);
|
||||
|
||||
IPFW_CTX_RLOCK();
|
||||
for (int i = 1; i < IP_FW_MAXCTX; i++) {
|
||||
if (V_ip_fw_contexts.chain[i] == NULL)
|
||||
continue;
|
||||
TAILQ_FOREACH(tmpifl, &V_ip_fw_contexts.iflist[i], entry) {
|
||||
if (strlen(tmpifl->ifname) != strlen(ifp->if_xname))
|
||||
continue;
|
||||
if (!strcmp(tmpifl->ifname, ifp->if_xname)) {
|
||||
printf("Restoring context for interface %s to %d\n", ifp->if_xname, i);
|
||||
ifp->if_ispare[0] = i;
|
||||
goto ifctxdone;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
ifctxdone:
|
||||
IPFW_CTX_RUNLOCK();
|
||||
|
||||
CURVNET_RESTORE();
|
||||
}
|
||||
|
||||
#define RULE_MAXSIZE (256*sizeof(u_int32_t))
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue