# $Id$
+#
# Top level makefile for building ipfw kernel and userspace.
# You can run it manually or also under the Planetlab build.
# Planetlab wants also the 'install' target.
+#
+# To build on system with non standard Kernel sources or userland files,
+# you should run this with
+#
+# make KERNELPATH=/path/to/linux-2.x.y.z USRDIR=/path/to/usr
+#
+# We assume that $(USRDIR) contains include/ and lib/ used to build userland.
DATE ?= $(shell date +%Y%m%d)
SNAPSHOT_NAME=ipfw_linux-$(DATE)
- fetch and extract the code e.g.
(cd ..; \
- wget http://info.iet.unipi.it/~luigi/dummynet/ipfw_linux-20090622.tgz;\
- tar xvzf ipfw_linux-20090622.tgz)
+ wget http://info.iet.unipi.it/~luigi/dummynet/ipfw_linux-20090724.tgz;\
+ tar xvzf ipfw_linux-20090724.tgz; mv ipfw_linux-20090724 ipfw_mod;)
(but you should have done it already)
- run the following commands:
- (mkdir packages/ipfw2;
- cp ../ipfw_mod/Makefile.openwrt packages/ipfw2/Makefile)
+ (mkdir package/ipfw2;
+ cp ../ipfw_linux/Makefile.openwrt package/ipfw2/Makefile)
to create the package/ipfw2 directory in the OpenWrt source
directory, and copy Makefile.openwrt to package/ipfw2/Makefile:
*/
#ifndef _WIN32 /* this is the linux version */
+/*
+ * XXX On zeroshell (2.6.25.17) we get a load error
+ * __you_cannot_kmalloc_that_much
+ * which is triggered when kmalloc() is called with a large
+ * compile-time constant argument (include/linux/slab_def.h)
+ *
+ * I think it may be a compiler (or source) bug because there is no
+ * evidence that such a large request is made.
+ * Making the _size argument to kmalloc volatile prevents the compiler
+ * from making the mistake, though it is clearly not ideal.
+ */
+
#if !defined (LINUX_24) && LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22)
#define malloc(_size, type, flags) \
- kmalloc(_size, GFP_ATOMIC | __GFP_ZERO)
+ ({ volatile int _v = _size; kmalloc(_v, GFP_ATOMIC | __GFP_ZERO); })
#else /* LINUX <= 2.6.22 and LINUX_24 */
/* linux 2.6.22 does not zero allocated memory */
#define malloc(_size, type, flags) \
* Below, the rt_unref is only needed when (pkt->dn_dir == DN_TO_IP_OUT)
* Doing this would probably save us the initial bzero of dn_pkt
*/
+#if defined( __linux__ )
+#define DN_FREE_PKT(_m) do { \
+ netisr_dispatch(-1, _m); \
+} while (0)
+#else
#define DN_FREE_PKT(_m) do { \
m_freem(_m); \
} while (0)
+#endif
/*
* Dispose all packets and flow_queues on a flow_set.
int match = 0;
struct sk_buff *skb = ((struct mbuf *)inp)->m_skb;
-#if 0 /* debug */
- printf("%s opcode %d arg %d oif %p src 0x%x:%d dst 0x%x:%d\n", __FUNCTION__,
- insn->o.opcode, insn->d[0], oif,
- ntohl(src_ip.s_addr), ntohs(src_port),
- ntohl(dst_ip.s_addr), ntohs(dst_port)
- );
-#endif
- if (insn->o.opcode == O_JAIL) {
-#ifdef IPFW_PLANETLAB
- match = (skb->skb_tag == insn->d[0]);
-#if 0 /* debug */
- printf("JAIL compiled for planetlab xid %d want %d result %d\n",
- skb->skb_tag, insn->d[0], match);
-#endif
-
-#endif
- return match;
- }
-
if (*ugid_lookupp == 0) { /* actively lookup and copy in cache */
/* returns null if any element of the chain up to file is null.
if (insn->o.opcode == O_UID)
match = (ugp->fw_uid == (uid_t)insn->d[0]);
+ else if (insn->o.opcode == O_JAIL)
+ match = (ugp->fw_groups[1] == (uid_t)insn->d[0]);
+ else if (insn->o.opcode == O_GID)
+ match = (ugp->fw_groups[0] == (uid_t)insn->d[0]);
+
return match;
#else /* FreeBSD */
/* end of ipv6 variables */
int is_ipv4 = 0;
+ int done = 0; /* flag for actions match */
+
if (m->m_flags & M_SKIP_FIREWALL)
return (IP_FW_PASS); /* accept */
uint32_t tablearg = 0;
int l, cmdlen, skip_or; /* skip rest of OR block */
-again:
+/* again: */
if (set_disable & (1 << f->set) )
continue;
* the target rule.
*/
-check_body:
+/* check_body: */
cmdlen = F_LEN(cmd);
/*
* An OR block (insn_1 || .. || insn_n) has the
* Exceptions:
* O_COUNT and O_SKIPTO actions:
* instead of terminating, we jump to the next rule
- * ('goto next_rule', equivalent to a 'break 2'),
- * or to the SKIPTO target ('goto again' after
+ * ('break' after setting match and l)
+ * or to the SKIPTO target ('break' after
* having set f, cmd and l), respectively.
*
* O_TAG, O_LOG and O_ALTQ action parameters:
* O_PROBE_STATE and O_CHECK_STATE: these opcodes
* cause a lookup of the state table, and a jump
* to the 'action' part of the parent rule
- * ('goto check_body') if an entry is found, or
+ * if an entry is found, or
* (CHECK_STATE only) a jump to the next rule if
* the entry is not found ('goto next_rule').
* The result of the lookup is cached to make
* further instances of these opcodes are
* effectively NOPs.
+ * The jump to the next rule is done by a break
+ * after zeroing the cmdlen value and setting
+ * match.
*/
case O_LIMIT:
case O_KEEP_STATE:
if (install_state(f,
(ipfw_insn_limit *)cmd, args, tablearg)) {
retval = IP_FW_DENY;
- goto done; /* error/limit violation */
+ /* was goto done; */ /* error/limit violation */
+ l = 0; /* break the inner loop */
+ done = 1; /* break the external loop */
}
match = 1;
break;
cmd = ACTION_PTR(f);
l = f->cmd_len - f->act_ofs;
IPFW_DYN_UNLOCK();
- goto check_body;
+ /* previously was goto check_body; */
+ cmdlen = 0; /* make null for() changes */
+ match = 1; /* do not break to the external loop */
+ break;
}
/*
* Dynamic entry not found. If CHECK_STATE,
* ignore and continue with next opcode.
*/
if (cmd->opcode == O_CHECK_STATE)
- goto next_rule;
+ l = 0; /* was goto next_rule; */
match = 1;
break;
case O_ACCEPT:
retval = 0; /* accept */
- goto done;
+ /* was goto done; */
+ l = 0; /* break the inner loop */
+ done = 1; /* break the external loop */
+ break;
case O_PIPE:
case O_QUEUE:
else
args->cookie = cmd->arg1;
retval = IP_FW_DUMMYNET;
- goto done;
+ /* was goto done; */
+ l = 0; /* break the inner loop */
+ done = 1; /* break the external loop */
+ break;
#if 0
case O_DIVERT:
m_tag_prepend(m, mtag);
retval = (cmd->opcode == O_DIVERT) ?
IP_FW_DIVERT : IP_FW_TEE;
- goto done;
+ /* was goto done; */
+ l = 0; /* break the inner loop */
+ done = 1; /* break the external loop */
+ break;
}
#endif
f->pcnt++; /* update stats */
f->bcnt += pktlen;
f->timestamp = time_uptime;
- if (cmd->opcode == O_COUNT)
- goto next_rule;
+ if (cmd->opcode == O_COUNT) {
+ /* was goto next_rule; */
+ l = 0; /* exit the inner loop */
+ match = 1; /* do not break the loop */
+ break;
+ }
/* handle skipto */
if (cmd->arg1 == IP_FW_TABLEARG) {
f = lookup_next_rule(f, tablearg);
lookup_next_rule(f, 0);
f = f->next_rule;
}
- goto again;
+ /* previously was "goto again;"
+ * We emulate by re-entering the inner loop
+ * with the correct f, l and cmd.
+ * First, skip over disabled rules.
+ * Should at least match the default rule,
+ * but try to be robust.
+ */
+ while (f && (set_disable & (1 << f->set)))
+ f = f->next;
+ /* prepare to re-enter the inner loop. */
+ if (f) { /* better safe than sorry */
+ l = f->cmd_len;
+ cmd = f->cmd;
+ } else {
+ l = 0; /* this will break the inner loop */
+ }
+ cmdlen = 0; /* reset loop condition */
+ skip_or = 0;
+ match = 1; /* do not break the loop */
+ break;
case O_REJECT:
/*
#endif
case O_DENY:
retval = IP_FW_DENY;
- goto done;
+ /* goto done; */
+ l = 0; /* break the inner loop */
+ done = 1; /* break the external loop */
+ break;
case O_FORWARD_IP: {
struct sockaddr_in *sa;
}
retval = IP_FW_PASS;
}
- goto done;
+ /* goto done; */
+ l = 0; /* break the inner loop */
+ done = 1; /* break the external loop */
+ break;
case O_NETGRAPH:
case O_NGTEE:
args->cookie = cmd->arg1;
retval = (cmd->opcode == O_NETGRAPH) ?
IP_FW_NETGRAPH : IP_FW_NGTEE;
- goto done;
+ /* goto done; */
+ l = 0; /* break the inner loop */
+ done = 1; /* break the external loop */
+ break;
#if 0
case O_SETFIB:
f->timestamp = time_uptime;
M_SETFIB(m, cmd->arg1);
args->f_id.fib = cmd->arg1;
- goto next_rule;
+ /* was goto next_rule; */
+ l = 0;
+ match = 1;
+ break;
case O_NAT: {
struct cfg_nat *t;
LOOKUP_NAT(layer3_chain, nat_id, t);
if (t == NULL) {
retval = IP_FW_DENY;
- goto done;
+ /* goto done; */
+ l = 0; /* break the inner loop */
+ done = 1; /* break the external loop */
+ break;
}
if (cmd->arg1 != IP_FW_TABLEARG)
((ipfw_insn_nat *)cmd)->nat = t;
retval = ipfw_nat_ptr(args, t, m);
} else
retval = IP_FW_DENY;
- goto done;
+ /* goto done; */
+ l = 0; /* break the inner loop */
+ done = 1; /* break the external loop */
+ break;
}
#endif
} /* end of inner for, scan opcodes */
-next_rule:; /* try next rule */
+ if (done)
+ break;
+/* next_rule:; */ /* try next rule */
} /* end of outer for, scan rules */
+
+ if (done) {
+ /* Update statistics */
+ f->pcnt++;
+ f->bcnt += pktlen;
+ f->timestamp = time_uptime;
+ IPFW_RUNLOCK(chain);
+ return (retval);
+ }
+
printf("ipfw: ouch!, skip past end of rules, denying packet\n");
IPFW_RUNLOCK(chain);
return (IP_FW_DENY);
-done:
- /* Update statistics */
- f->pcnt++;
- f->bcnt += pktlen;
- f->timestamp = time_uptime;
- IPFW_RUNLOCK(chain);
- return (retval);
-
pullup_failed:
if (fw_verbose)
printf("ipfw: pullup failed\n");
}
/*
- * Copy the static and dynamic rules to the supplied buffer
+ * Copy the static rules to the supplied buffer
* and return the amount of space actually used.
*/
static size_t
time_t boot_seconds;
boot_seconds = boottime.tv_sec;
+
/* XXX this can take a long time and locking will block packet flow */
IPFW_RLOCK(chain);
for (rule = chain->rules; rule ; rule = rule->next) {
}
}
IPFW_RUNLOCK(chain);
+
+ return (bp - (char *)buf);
+}
+
+/*
+ * Copy the dynamic rules to the supplied buffer
+ * and return the amount of space actually used.
+ * XXX marta if we allocate X and rules grows
+ * we check for size limit while copying rules into the buffer
+ */
+static size_t
+ipfw_getdynrules(struct ip_fw_chain *chain, void *buf, size_t space)
+{
+ char *bp = buf;
+ char *ep = bp + space;
+ int i;
+ time_t boot_seconds;
+
+ printf("dynrules requested\n");
+ boot_seconds = boottime.tv_sec;
+
if (ipfw_dyn_v) {
ipfw_dyn_rule *p, *last = NULL;
TIME_LEQ(dst->expire, time_uptime) ?
0 : dst->expire - time_uptime ;
bp += sizeof(ipfw_dyn_rule);
+ } else {
+ p = NULL; /* break the loop */
+ i = curr_dyn_buckets;
}
}
IPFW_DYN_UNLOCK();
if (last != NULL) /* mark last dynamic rule */
bzero(&last->next, sizeof(last));
}
+
return (bp - (char *)buf);
}
switch (sopt->sopt_name) {
case IP_FW_GET:
/*
- * pass up a copy of the current rules. Static rules
- * come first (the last of which has number IPFW_DEFAULT_RULE),
- * followed by a possibly empty list of dynamic rule.
- * The last dynamic rule has NULL in the "next" field.
+ * pass up a copy of the current static rules.
+ * The last static rule has number IPFW_DEFAULT_RULE.
*
* Note that the calculated size is used to bound the
* amount of data returned to the user. The rule set may
* data in which case we'll just return what fits.
*/
size = static_len; /* size of static rules */
- if (ipfw_dyn_v) /* add size of dyn.rules */
- size += (dyn_count * sizeof(ipfw_dyn_rule));
/*
* XXX todo: if the user passes a short length just to know
free(buf, M_TEMP);
break;
+ case IP_FW_DYN_GET:
+ /*
+ * pass up a copy of the current dynamic rules.
+ * The last dynamic rule has NULL in the "next" field.
+ */
+ /* if (!ipfw_dyn_v) XXX check for empty set ? */
+ size = (dyn_count * sizeof(ipfw_dyn_rule)); /* size of dyn. rules */
+
+ buf = malloc(size, M_TEMP, M_WAITOK);
+ error = sooptcopyout(sopt, buf,
+ ipfw_getdynrules(&layer3_chain, buf, size));
+ free(buf, M_TEMP);
+ break;
+
case IP_FW_FLUSH:
/*
* Normally we cannot release the lock on each iteration.
#endif
/*
- * ipfw hooks the POST_ROUTING and the PRE_ROUTING chain.
- * PlanetLab tags the xid in the LOCAL_INPUT and in the
- * POST_ROUTING chain, so if we want to intercept the
- * traffic by using the id we need to hook the LOCAL_INPUT
- * chain instead of the PRE_ROUTING.
+ * ipfw hooks into the POST_ROUTING and the PRE_ROUTING chains.
+ * PlanetLab sets skb_tag to the slice id in the LOCAL_INPUT and
+ * POST_ROUTING chains, so if we want to use that information we
+ * need to hook the LOCAL_INPUT chain instead of the PRE_ROUTING.
+ * However at the moment the skb_tag info is not reliable so
+ * we stay with the standard hooks.
*/
-#ifdef IPFW_PLANETLAB
+#if 0 // defined(IPFW_PLANETLAB)
#define IPFW_HOOK_IN NF_IP_LOCAL_IN
#else
#define IPFW_HOOK_IN NF_IP_PRE_ROUTING
*
* We do this only on selected protocols: TCP, ...
*
- * Note- for locally generated, outgoing packets we don't need to
- * do a lookup because the sk_buff already points to the socket where
+ * The chain is the following
+ * sk_buff* sock* socket* file*
+ * skb -> sk ->sk_socket->file ->f_owner ->pid
+ * skb -> sk ->sk_socket->file ->f_uid (direct)
+ * skb -> sk ->sk_socket->file ->f_cred->fsuid (2.6.29+)
+ *
+ * Related headers:
+ * linux/skbuff.h struct skbuff
+ * net/sock.h struct sock
+ * linux/net.h struct socket
+ * linux/fs.h struct file
+ *
+ * With vserver we may have sk->sk_xid and sk->sk_nid that
+ * which we store in fw_groups[1] (matches O_JAIL) and fw_groups[2]
+ * (no matches yet)
+ *
+ * Note- for locally generated, outgoing packets we should not need
+ * need a lookup because the sk_buff already points to the socket where
* the info is.
*/
extern struct inet_hashinfo tcp_hashinfo;
*/
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,24)
#define _OPT_NET_ARG
-#else /* 2.6.25 and above */
+#else
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
+/* there is no dev_net() on 2.6.25 */
+#define _OPT_NET_ARG (skb->dev->nd_net),
+#else /* 2.6.26 and above */
#define _OPT_NET_ARG dev_net(skb->dev),
+#endif
#endif
+ if (0 && skb->sk) {
+ sk=skb->sk;
+ } else {
sk = (dir) ?
inet_lookup(_OPT_NET_ARG &tcp_hashinfo,
daddr, dport, saddr, sport, // matches outgoing for server sockets
inet_lookup(_OPT_NET_ARG &tcp_hashinfo,
saddr, sport, daddr, dport, // matches incoming for server sockets
skb->dev->ifindex);
+ }
#undef _OPT_NET_ARG
/* no match, nothing to be done */
sk->sk_socket && sk->sk_socket->file) {
ugp->fw_uid = sk->sk_socket->file->_CURR_UID;
uid = ugp->fw_uid;
+ ugp->fw_groups[0] = sk->sk_socket->file->_CURR_GID;
+#ifdef CONFIG_VSERVER
+ ugp->fw_groups[1] = sk->sk_xid;
+ ugp->fw_groups[2] = sk->sk_nid;
+#endif
ret = 1;
}
- sock_put(sk);
+ if (1 && !skb->sk) /* the reference came from the lookup */
+ sock_put(sk);
#undef _CURR_UID
#undef _CURR_GID
/*
* $Id$
+ *
* Header for kernel variables and functions that are not available in
* userland.
*/
* SUCH DAMAGE.
*/
/*
- *
* $Id$
*
* glue code to adapt the FreeBSD version to linux and windows,
void
qsort_r(void *a, size_t n, size_t es, void *thunk,
int cmp_t(void *, const void *, const void *));
-#define heapsort(_a, _b, _c, _d) qsort(_a, _b, _c, _d)
#define setprogname(x) /* not present in linux */
# enable extra debugging information
# Do not set with = or := so we can inherit from the caller
$(warning Building userland ipfw for $(VER))
-EXTRA_CFLAGS +=
EXTRA_CFLAGS += -O1
+# comment this on planetlab
+# EXTRA_CFLAGS += -Wall -Werror
EXTRA_CFLAGS += -include ../glue.h
-
-LDFLAGS=
-
EXTRA_CFLAGS += -I ./include
ifneq ($(VER),openwrt)
endif # !openwrt
CFLAGS += $(EXTRA_CFLAGS)
+# Location of OS headers and libraries. After our stuff.
+USRDIR?= /usr
+CFLAGS += -I$(USRDIR)/include
+LDFLAGS += -L$(USRDIR)/lib
-OBJS = ipfw2.o dummynet.o main.o ipv6.o altq.o
+OBJS = ipfw2.o dummynet.o main.o ipv6.o altq.o qsort_r.o
ifneq ($(HAVE_NAT),)
OBJS += nat.o
EXTRA_CFLAGS += -DHAVE_NAT
#!/bin/bash
+#
+# A test script to add rules
PRG=./ipfw
{ NULL, 0 } /* terminator */
};
+/*
+ * XXX to be updated to the new version,
+ * without the global struct command_opts variable
+ */
static int
-sort_q(const void *pa, const void *pb)
+sort_q(void * to_be_done, const void *pa, const void *pb)
{
int rev = (co.do_sort < 0);
int field = rev ? -co.do_sort : co.do_sort;
return;
if (co.do_sort != 0)
- heapsort(q, fs->rq_elements, sizeof *q, sort_q);
+ qsort_r(q, fs->rq_elements, sizeof *q, NULL, sort_q);
/* Print IPv4 flows */
index_printed = 0;
* and return the numeric bandwidth value.
* set clocking interface or bandwidth value
*/
-void
+static void
read_bandwidth(char *arg, int *bandwidth, char *if_name, int namelen)
{
if (*bandwidth != -1)
double delay;
};
-int
+static int
compare_points(const void *vp1, const void *vp2)
{
const struct point *p1 = vp1;
if (s < 0)
err(EX_UNAVAILABLE, "socket");
- if (optname == IP_FW_GET || optname == IP_DUMMYNET_GET ||
+ if (optname == IP_FW_GET || optname == IP_FW_DYN_GET ||
+ optname == IP_DUMMYNET_GET ||
optname == IP_FW_ADD || optname == IP_FW_TABLE_LIST ||
optname == IP_FW_TABLE_GETSIZE ||
optname == IP_FW_NAT_GET_CONFIG ||
ipfw_list(int ac, char *av[], int show_counters)
{
struct ip_fw *r;
- ipfw_dyn_rule *dynrules, *d;
+ ipfw_dyn_rule *dynrules = NULL;
+ ipfw_dyn_rule *d;
#define NEXT(r) ((struct ip_fw *)((char *)r + RULESIZE(r)))
char *lim;
void *data = NULL;
- int bcwidth, n, nbytes, nstat, ndyn, pcwidth, width;
+ int bcwidth, n, nbytes, pcwidth, width, nstat;
+ int ndyn = 0;
int exitval = EX_OK;
int lac;
char **lav;
char *endptr;
int seen = 0;
uint8_t set;
+ int ocmd = IP_FW_GET;
+
+ if (co.do_pipe)
+ ocmd = IP_DUMMYNET_GET;
+ else if (co.do_dynamic)
+ ocmd = IP_FW_DYN_GET;
- const int ocmd = co.do_pipe ? IP_DUMMYNET_GET : IP_FW_GET;
int nalloc = 1024; /* start somewhere... */
last = 0;
* Count static rules. They have variable size so we
* need to scan the list to count them.
*/
+ nstat = 0;
+ r = data;
+
+ if (!co.do_dynamic) {
for (nstat = 1, r = data, lim = (char *)data + nbytes;
r->rulenum < IPFW_DEFAULT_RULE && (char *)r < lim;
++nstat, r = NEXT(r) )
; /* nothing */
+ }
/*
* Count dynamic rules. This is easier as they have
* fixed size.
*/
- r = NEXT(r);
- dynrules = (ipfw_dyn_rule *)r ;
- n = (char *)r - (char *)data;
- ndyn = (nbytes - n) / sizeof *dynrules;
+ if (co.do_dynamic) {
+ dynrules = (ipfw_dyn_rule *)r ;
+ n = (char *)r - (char *)data;
+ ndyn = (nbytes - n) / sizeof *dynrules;
+ }
/* if showing stats, figure out column widths ahead of time */
bcwidth = pcwidth = 0;
bcwidth = width;
}
}
+
if (co.do_dynamic && ndyn) {
for (n = 0, d = dynrules; n < ndyn; n++, d++) {
if (co.use_set) {
bcwidth = width;
}
}
+
/* if no rule numbers were specified, list all rules */
if (ac == 0) {
for (n = 0, r = data; n < nstat; n++, r = NEXT(r)) {
/* display specific rules requested on command line */
+ if (!co.do_dynamic) {
for (lac = ac, lav = av; lac != 0; lac--) {
/* convert command line rule # */
last = rnum = strtoul(*lav++, &endptr, 10);
warnx("rule %lu does not exist", rnum);
}
}
+ }
if (co.do_dynamic && ndyn) {
printf("## Dynamic rules:\n");
#!/bin/sh
#
-# Marta Carbone
+# Marta Carbone, Luigi Rizzo
# Copyright (C) 2009 Universita` di Pisa
# $Id$
#
-# This script is the frontend to be used with
-# the vsys system.
-# It allows to configure dummynet pipes and queues.
-# In detail it:
-# - get user input
-# - send command to the vsys input pipe
-# - wait a bit
-# - get the reply from the output vsys pipe
-# - show the output to the user
-#
-# A simple usage is:
-# ./netconfig -p 9898 <dummynet configuration parameters>
-# mandatory fields are the port to be configured
-# and dummynet configuration parameters
+# This script is the frontend to be used with the vsys system.
+# It simply passes information to the backend and gets back the reply
PIPE_IN=/vsys/ipfw-be.in
PIPE_OUT=/vsys/ipfw-be.out
-LOGFILE=/tmp/netconfig.log
-SED=/bin/sed # used to extract the profile name
-DEBUG=0 # 0 disable debug messages
-prog=$0 # this program
-
-# Print the first argument and exit
-abort()
-{
- echo "$1"; exit 1
-}
-
-# if $DEBUG is enabled, print a debug message
-# $1 the message to print
-debug()
-{
- [ "${DEBUG}" != "0" ] && echo "$1" >> ${LOGFILE}
-}
-
-# print the usage and exit
-help()
-{
- cat << EOF
-Usage: $prog -p port [-U] [-t timeout[STRING]] ipfw_configuration_parameters \n
- $prog ipfw show \n
- $prog pipe show \n
-
- -h show help \n
- -p specify the port to configure \n
- -d delete specified rules and pipes \n
- -t specify the timeout. STRING can be "1minute" or "4hours" (default 1 hour) \n
-
- ipfw configuration parameters (mandatory) \n
- extra-delay <filename> bw <value> delay <value> proto... plr... \n
-
- ipfw show show the ipfw ruleset
- ipfw pipe show the configured pipes
-EOF
- exit 0
-}
-
-# parse input line and fill missing fields
-parse_input()
-{
- # counters used to check if at least
- # two ipfw configuration parameters are present
- local OPT_ARGS=2 # optional (timeout)
- local MAND_ARGS=2 # mandatory (port)
-
- [ -z "$1" ] && help;
-
- while getopts ":hdp:t:" opt; do
- case $opt in
- h | \?) help;;
- p) PORT=$OPTARG;;
- d) DELETE=1;;
- t) TIMEOUT=$OPTARG;;
- esac
- done
-
- # check for mandatory arguments
- [ -z ${PORT} ] && abort "a port value is mandatory";
-
- # the default value for the timeout is 1H
- if [ -z ${TIMEOUT} ]; then
- TIMEOUT="1hour"
- OPT_ARGS=$((${OPT_ARGS}-2))
- fi
-
- # check for deletion flag
- if [ -z ${DELETE} ]; then
- DELETE=0
- else
- # if d is present configuration is not required
- MAND_ARGS=$((${MAND_ARGS}-2))
- fi
-
- # compute residue argument, we need at least 2
- # mandatory arguments (for ipfw), exit on error
- # debug "Passed args $# Mandatory ${MAND_ARGS} Optional ${OPT_ARGS} Extra $(($#-${MAND_ARGS}-${OPT_ARGS}))"
- if [ $(($#-${MAND_ARGS}-${OPT_ARGS})) -lt 2 ]; then
- help
- fi
-}
-
-# the backend expects lines in the format:
-# ipfw
-# pipe
-# port timeout configuration_string
-# main starts here
-
- # allow ipfw show and ipfw pipe show commands
- if [ x$1 = x"ipfw" ]; then
- echo "received" $1
- echo "ipfw" >> ${PIPE_IN}
- cat ${PIPE_OUT}
- exit 0;
- else if [ x$1 = x"pipe" ]; then
- echo "pipe" >> ${PIPE_IN}
- cat ${PIPE_OUT}
- exit 0;
- fi
- fi
-
- # parse the input
- parse_input $*
- shift $((${OPTIND}-1));
-
- # print debug
- debug "PORT ${PORT}"
- debug "DELETE ${DELETE}"
- debug "TIMEOUT ${TIMEOUT}"
- debug "PIPE_CONFIGURATION $*"
-
- # format CMD as expected by the backend script
- CMD="${PORT} ${TIMEOUT} ${DELETE} $*";
-
- # send the command
- debug "Sending: ${CMD}"
- echo ${CMD} >> ${PIPE_IN}
-
- cat ${PIPE_OUT}
+sudo sh -c "echo $* >> ${PIPE_IN}"
+sudo sh -c "cat ${PIPE_OUT}"