📄 ipfw.c.svn-base
字号:
par = &pipe.fs.flow_mask.src_port;
else if (!strncmp(*av, "proto", len))
par = &pipe.fs.flow_mask.proto;
else
break;
if (ac < 2)
errx(EX_USAGE, "mask: %s value"
" missing", *av);
if (*av[1] == '/') {
a = strtoul(av[1]+1, &end, 0);
if (a == 32) /* special case... */
a = ~0;
else
a = (1 << a) - 1;
fprintf(stderr, " mask is 0x%08x\n", a);
} else {
a = strtoul(av[1], &end, 0);
}
if (par == &pipe.fs.flow_mask.src_port
|| par == &pipe.fs.flow_mask.dst_port) {
if (a >= (1 << 16))
errx(EX_DATAERR, "mask: %s"
" must be 16 bit, not"
" 0x%08x", *av, a);
*((u_int16_t *)par) = (u_int16_t)a;
} else if (par == &pipe.fs.flow_mask.proto) {
if (a >= (1 << 8))
errx(EX_DATAERR, "mask: %s"
" must be"
" 8 bit, not 0x%08x",
*av, a);
*((u_int8_t *)par) = (u_int8_t)a;
} else
*((u_int32_t *)par) = a;
if (a != 0)
pipe.fs.flags_fs |= DN_HAVE_FLOW_MASK;
av += 2;
ac -= 2;
} /* end for */
} else if (!strncmp(*av, "red", strlen(*av))
|| !strncmp(*av, "gred", strlen(*av))) {
/* RED enabled */
pipe.fs.flags_fs |= DN_IS_RED;
if (*av[0] == 'g')
pipe.fs.flags_fs |= DN_IS_GENTLE_RED;
if ((end = strsep(&av[1], "/"))) {
double w_q = strtod(end, NULL);
if (w_q > 1 || w_q <= 0)
errx(EX_DATAERR, "w_q %f must be "
"0 < x <= 1", w_q);
pipe.fs.w_q = (int) (w_q * (1 << SCALE_RED));
}
if ((end = strsep(&av[1], "/"))) {
pipe.fs.min_th = strtoul(end, &end, 0);
if (*end == 'K' || *end == 'k')
pipe.fs.min_th *= 1024;
}
if ((end = strsep(&av[1], "/"))) {
pipe.fs.max_th = strtoul(end, &end, 0);
if (*end == 'K' || *end == 'k')
pipe.fs.max_th *= 1024;
}
if ((end = strsep(&av[1], "/"))) {
double max_p = strtod(end, NULL);
if (max_p > 1 || max_p <= 0)
errx(EX_DATAERR, "max_p %f must be "
"0 < x <= 1", max_p);
pipe.fs.max_p =
(int)(max_p * (1 << SCALE_RED));
}
av += 2;
ac -= 2;
} else if (!strncmp(*av, "droptail", strlen(*av))) {
/* DROPTAIL */
pipe.fs.flags_fs &= ~(DN_IS_RED|DN_IS_GENTLE_RED);
av += 1;
ac -= 1;
} else {
int len = strlen(*av);
if (do_pipe == 1) {
/* some commands are only good for pipes. */
if (!strncmp(*av, "bw", len)
|| !strncmp(*av, "bandwidth", len)) {
if (av[1][0] >= 'a'
&& av[1][0] <= 'z') {
int l = sizeof(pipe.if_name)-1;
/* interface name */
strncpy(pipe.if_name, av[1], l);
pipe.if_name[l] = '\0';
pipe.bandwidth = 0;
} else {
pipe.if_name[0] = '\0';
pipe.bandwidth =
strtoul(av[1], &end, 0);
if (*end == 'K'
|| *end == 'k') {
end++;
pipe.bandwidth *=
1000;
} else if (*end == 'M') {
end++;
pipe.bandwidth *=
1000000;
}
if (*end == 'B'
|| !strncmp(end, "by", 2))
pipe.bandwidth *= 8;
}
if (pipe.bandwidth < 0)
errx(EX_DATAERR,
"bandwidth too large");
av += 2;
ac -= 2;
} else if (!strncmp(*av, "delay", len)) {
pipe.delay = strtoul(av[1], NULL, 0);
av += 2;
ac -= 2;
} else {
errx(EX_DATAERR, "unrecognised pipe"
" option ``%s''", *av);
}
} else { /* this refers to a queue */
if (!strncmp(*av, "weight", len)) {
pipe.fs.weight =
strtoul(av[1], &end, 0);
av += 2;
ac -= 2;
} else if (!strncmp(*av, "pipe", len)) {
pipe.fs.parent_nr =
strtoul(av[1], &end, 0);
av += 2;
ac -= 2;
} else {
errx(EX_DATAERR, "unrecognised option "
"``%s''", *av);
}
}
}
}
if (do_pipe == 1) {
if (pipe.pipe_nr == 0)
errx(EX_DATAERR, "pipe_nr %d must be > 0",
pipe.pipe_nr);
if (pipe.delay > 10000)
errx(EX_DATAERR, "delay %d must be < 10000",
pipe.delay);
} else { /* do_pipe == 2, queue */
if (pipe.fs.parent_nr == 0)
errx(EX_DATAERR, "pipe %d must be > 0",
pipe.fs.parent_nr);
if (pipe.fs.weight >100)
errx(EX_DATAERR, "weight %d must be <= 100",
pipe.fs.weight);
}
if (pipe.fs.flags_fs & DN_QSIZE_IS_BYTES) {
if (pipe.fs.qsize > 1024*1024)
errx(EX_DATAERR, "queue size %d, must be < 1MB",
pipe.fs.qsize);
} else {
if (pipe.fs.qsize > 100)
errx(EX_DATAERR, "queue size %d, must be"
" 2 <= x <= 100", pipe.fs.qsize);
}
if (pipe.fs.flags_fs & DN_IS_RED) {
size_t len;
int lookup_depth, avg_pkt_size;
double s, idle, weight, w_q;
struct clockinfo clock;
int t;
if (pipe.fs.min_th >= pipe.fs.max_th)
errx(EX_DATAERR, "min_th %d must be < than max_th %d",
pipe.fs.min_th, pipe.fs.max_th);
if (pipe.fs.max_th == 0)
errx(EX_DATAERR, "max_th must be > 0");
len = sizeof(int);
if (sysctlbyname("net.inet.ip.dummynet.red_lookup_depth",
&lookup_depth, &len, NULL, 0) == -1)
errx(1, "sysctlbyname(\"%s\")",
"net.inet.ip.dummynet.red_lookup_depth");
if (lookup_depth == 0)
errx(EX_DATAERR, "net.inet.ip.dummynet.red_lookup_depth"
" must be greater than zero");
len = sizeof(int);
if (sysctlbyname("net.inet.ip.dummynet.red_avg_pkt_size",
&avg_pkt_size, &len, NULL, 0) == -1)
errx(1, "sysctlbyname(\"%s\")",
"net.inet.ip.dummynet.red_avg_pkt_size");
if (avg_pkt_size == 0)
errx(EX_DATAERR,
"net.inet.ip.dummynet.red_avg_pkt_size must"
" be greater than zero");
len = sizeof(struct clockinfo);
if (sysctlbyname("kern.clockrate", &clock, &len, NULL, 0) == -1)
errx(1, "sysctlbyname(\"%s\")",
"kern.clockrate");
/*
* Ticks needed for sending a medium-sized packet.
* Unfortunately, when we are configuring a WF2Q+ queue, we
* do not have bandwidth information, because that is stored
* in the parent pipe, and also we have multiple queues
* competing for it. So we set s=0, which is not very
* correct. But on the other hand, why do we want RED with
* WF2Q+ ?
*/
if (pipe.bandwidth==0) /* this is a WF2Q+ queue */
s = 0;
else
s = clock.hz * avg_pkt_size * 8 / pipe.bandwidth;
/*
* max idle time (in ticks) before avg queue size
* becomes 0.
* NOTA: (3/w_q) is approx the value x so that
* (1-w_q)^x < 10^-3.
*/
w_q = ((double)pipe.fs.w_q) / (1 << SCALE_RED);
idle = s * 3. / w_q;
pipe.fs.lookup_step = (int)idle / lookup_depth;
if (!pipe.fs.lookup_step)
pipe.fs.lookup_step = 1;
weight = 1 - w_q;
for (t = pipe.fs.lookup_step; t > 0; --t)
weight *= weight;
pipe.fs.lookup_weight = (int)(weight * (1 << SCALE_RED));
}
i = setsockopt(s, IPPROTO_IP, IP_DUMMYNET_CONFIGURE, &pipe,
sizeof pipe);
if (i)
err(1, "setsockopt(%s)", "IP_DUMMYNET_CONFIGURE");
}
#endif /* !_WIN32 */
static void
add(int ac, char *av[])
{
struct ip_fw rule;
int i;
u_char proto;
struct protoent *pe;
int saw_xmrc = 0, saw_via = 0;
memset(&rule, 0, sizeof rule);
av++; ac--;
/* Rule number */
if (ac && isdigit(**av)) {
rule.fw_number = atoi(*av); av++; ac--;
}
/* Action */
if (ac > 1 && !strncmp(*av, "prob", strlen(*av))) {
double d = strtod(av[1], NULL);
if (d <= 0 || d > 1)
errx(EX_DATAERR, "illegal match prob. %s", av[1]);
if (d != 1) { /* 1 means always match */
rule.fw_flg |= IP_FW_F_RND_MATCH;
rule.dont_match_prob = (long)((1 - d) * 0x7fffffff);
}
av += 2; ac -= 2;
}
if (ac == 0)
errx(EX_USAGE, "missing action");
if (!strncmp(*av, "accept", strlen(*av))
|| !strncmp(*av, "pass", strlen(*av))
|| !strncmp(*av, "allow", strlen(*av))
|| !strncmp(*av, "permit", strlen(*av))) {
rule.fw_flg |= IP_FW_F_ACCEPT; av++; ac--;
} else if (!strncmp(*av, "count", strlen(*av))) {
rule.fw_flg |= IP_FW_F_COUNT; av++; ac--;
} else if (!strncmp(*av, "pipe", strlen(*av))) {
rule.fw_flg |= IP_FW_F_PIPE; av++; ac--;
if (!ac)
errx(EX_USAGE, "missing pipe number");
rule.fw_divert_port = strtoul(*av, NULL, 0); av++; ac--;
} else if (!strncmp(*av, "queue", strlen(*av))) {
rule.fw_flg |= IP_FW_F_QUEUE; av++; ac--;
if (!ac)
errx(EX_USAGE, "missing queue number");
rule.fw_divert_port = strtoul(*av, NULL, 0); av++; ac--;
} else if (!strncmp(*av, "divert", strlen(*av))) {
rule.fw_flg |= IP_FW_F_DIVERT; av++; ac--;
if (!ac)
errx(EX_USAGE, "missing %s port", "divert");
rule.fw_divert_port = strtoul(*av, NULL, 0); av++; ac--;
if (rule.fw_divert_port == 0) {
struct servent *s;
setservent(1);
s = getservbyname(av[-1], "divert");
if (s != NULL)
rule.fw_divert_port = ntohs(s->s_port);
else
errx(EX_DATAERR, "illegal %s port", "divert");
}
} else if (!strncmp(*av, "tee", strlen(*av))) {
rule.fw_flg |= IP_FW_F_TEE; av++; ac--;
if (!ac)
errx(EX_USAGE, "missing %s port", "tee divert");
rule.fw_divert_port = strtoul(*av, NULL, 0); av++; ac--;
if (rule.fw_divert_port == 0) {
struct servent *s;
setservent(1);
s = getservbyname(av[-1], "divert");
if (s != NULL)
rule.fw_divert_port = ntohs(s->s_port);
else
errx(EX_DATAERR, "illegal %s port",
"tee divert");
}
} else if (!strncmp(*av, "fwd", strlen(*av))
|| !strncmp(*av, "forward", strlen(*av))) {
struct in_addr dummyip;
char *pp;
rule.fw_flg |= IP_FW_F_FWD; av++; ac--;
if (!ac)
errx(EX_USAGE, "missing forwarding IP address");
#ifndef _WIN32 /* no sin_len in Winsock! */
rule.fw_fwd_ip.sin_len = sizeof(struct sockaddr_in);
#endif
rule.fw_fwd_ip.sin_family = AF_INET;
rule.fw_fwd_ip.sin_port = 0;
pp = strchr(*av, ':');
if(pp == NULL)
pp = strchr(*av, ',');
if(pp != NULL)
{
*(pp++) = '\0';
i = lookup_port(pp, 0, 1, 0);
if (i == -1)
errx(EX_DATAERR, "illegal forwarding"
" port ``%s''", pp);
else
rule.fw_fwd_ip.sin_port = (u_short)i;
}
fill_ip(&(rule.fw_fwd_ip.sin_addr), &dummyip, &ac, &av);
if (rule.fw_fwd_ip.sin_addr.s_addr == 0)
errx(EX_DATAERR, "illegal forwarding IP address");
} else if (!strncmp(*av, "skipto", strlen(*av))) {
rule.fw_flg |= IP_FW_F_SKIPTO; av++; ac--;
if (!ac)
errx(EX_USAGE, "missing skipto rule number");
rule.fw_skipto_rule = strtoul(*av, NULL, 10); av++; ac--;
} else if ((!strncmp(*av, "deny", strlen(*av))
|| !strncmp(*av, "drop", strlen(*av)))) {
rule.fw_flg |= IP_FW_F_DENY; av++; ac--;
} else if (!strncmp(*av, "reject", strlen(*av))) {
rule.fw_flg |= IP_FW_F_REJECT; av++; ac--;
rule.fw_reject_code = ICMP_UNREACH_HOST;
} else if (!strncmp(*av, "reset", strlen(*av))) {
rule.fw_flg |= IP_FW_F_REJECT; av++; ac--;
rule.fw_reject_code = IP_FW_REJECT_RST; /* check TCP later */
} else if (!strncmp(*av, "unreach", strlen(*av))) {
rule.fw_flg |= IP_FW_F_REJECT; av++; ac--;
fill_reject_code(&rule.fw_reject_code, *av); av++; ac--;
} else if (!strncmp(*av, "check-state", strlen(*av))) {
rule.fw_flg |= IP_FW_F_CHECK_S; av++; ac--;
goto done;
} else {
errx(EX_DATAERR, "invalid action ``%s''", *av);
}
/* [log] */
if (ac && !strncmp(*av, "log", strlen(*av))) {
rule.fw_flg |= IP_FW_F_PRN; av++; ac--;
}
if (ac && !strncmp(*av, "logamount", strlen(*av))) {
if (!(rule.fw_flg & IP_FW_F_PRN))
errx(EX_USAGE, "``logamount'' not valid without"
" ``log''");
ac--; av++;
if (!ac)
errx(EX_USAGE, "``logamount'' requires argument");
rule.fw_logamount = atoi(*av);
if (rule.fw_logamount < 0)
errx(EX_DATAERR, "``logamount'' argument must be"
" positive");
if (rule.fw_logamount == 0)
rule.fw_logamount = -1;
ac--; av++;
}
/* protocol */
if (ac == 0)
errx(EX_USAGE, "missing protocol");
if ((proto = atoi(*av)) > 0) {
rule.fw_prot = proto; av++; ac--;
} else if (!strncmp(*av, "all", strlen(*av))) {
rule.fw_prot = IPPROTO_IP; av++; ac--;
} else if ((pe = getprotobyname(*av)) != NULL) {
rule.fw_prot = pe->p_proto; av++; ac--;
} else {
errx(EX_DATAERR, "invalid protocol ``%s''", *av);
}
if (rule.fw_prot != IPPROTO_TCP
&& (rule.fw_flg & IP_FW_F_COMMAND) == IP_FW_F_REJECT
&& rule.fw_reject_code == IP_FW_REJECT_RST)
errx(EX_DATAERR, "``reset'' is only valid for tcp packets");
/* from */
if (ac && !strncmp(*av, "from", strlen(*av))) { av++; ac--; }
else
errx(EX_USAGE, "missing ``from''");
if (ac && !strncmp(*av, "not", strlen(*av))) {
rule.fw_flg |= IP_FW_F_INVSRC;
av++; ac--;
}
if (!ac)
errx(EX_USAGE, "missing arguments");
if (ac && !strncmp(*av, "me", strlen(*av))) {
rule.fw_flg |= IP_FW_F_SME;
av++; ac--;
} else {
fill_ip(&rule.fw_src, &rule.fw_smsk, &ac, &av);
}
if (ac && (isdigit(**av)
|| lookup_port(*av, rule.fw_prot, 1, 1) >= 0)) {
u_short nports = 0;
int retval;
retval = fill_port(&nports, rule.fw_uar.fw_pts,
0, *av, rule.fw_prot);
if (retval == 1)
rule.fw_flg |= IP_FW_F_SRNG;
else if (retval == 2)
rule.fw_flg |= IP_FW_F_SMSK;
IP_FW_SETNSRCP(&rule, nports);
av++; ac--;
}
/* to */
if (ac && !strncmp(*av, "to", strlen(*av))) { av++; ac--; }
else
errx(EX_USAGE, "missing ``to''");
if (ac && !strncmp(*av, "not", strlen(*av))) {
rule.fw_flg |= IP_FW_F_INVDST;
av++; ac--;
}
if (!ac)
errx(EX_USAGE, "missing arguments");
if (ac && !strncmp(*av, "me", strlen(*av))) {
rule.fw_flg |= IP_FW_F_DME;
av++; ac--;
} else {
fill_ip(&rule.fw_dst, &rule.fw_dmsk, &ac, &av);
}
if (ac && (isdigit(**av)
|| lookup_port(*av, rule.fw_prot, 1, 1) >= 0)) {
u_short nports = 0;
int retval;
retval = fill_port(&nports, rule.fw_uar.fw_pts,
IP_FW_GETNSRCP(&rule), *av, rule.fw_prot);
if (retval == 1)
rule.fw_flg |= IP_FW_F_DRNG;
else if (retval == 2)
rule.fw_flg |= IP_FW_F_DMSK;
IP_FW_SETNDSTP(&rule, nports);
av++; ac--;
}
if ((rule.fw_prot != IPPROTO_TCP) && (rule.fw_prot != IPPROTO_UDP)
&& (IP_FW_GETNSRCP(&rule) || IP_FW_GETNDSTP(&rule))) {
errx(EX_USAGE, "only TCP and UDP protocols are valid"
" with port specifications");
}
while (ac) {
#ifndef _WIN32 /* no uid/gid checks for now! */
if (!strncmp(*av, "uid", strlen(*av))) {
struct passwd *pwd;
char *end;
uid_t uid;
rule.fw_flg |= IP_FW_F_UID;
ac--; av++;
if (!ac)
errx(EX_USAGE, "``uid'' requires argument");
uid = strtoul(*av, &end, 0);
if (*end == '\0')
pwd = getpwuid(uid);
else
pwd = getpwnam(*av);
if (pwd == NULL)
errx(EX_DATAERR, "uid \"%s\" is"
" nonexistent", *av);
rule.fw_uid = pwd->pw_uid;
ac--; av++;
} else if (!strncmp(*av, "gid", strlen(*av))) {
struct group *grp;
char *end;
gid_t gid;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -