📄 ipfw.c.svn-base
字号:
else if (chain->fw_tcpf || chain->fw_tcpnf) {
int _flg_printed = 0;
#define PRINTFLG(x) {if (_flg_printed) printf(",");\
printf(x); _flg_printed = 1;}
printf(" tcpflags ");
if (chain->fw_tcpf & IP_FW_TCPF_FIN)
PRINTFLG("fin");
if (chain->fw_tcpnf & IP_FW_TCPF_FIN)
PRINTFLG("!fin");
if (chain->fw_tcpf & IP_FW_TCPF_SYN)
PRINTFLG("syn");
if (chain->fw_tcpnf & IP_FW_TCPF_SYN)
PRINTFLG("!syn");
if (chain->fw_tcpf & IP_FW_TCPF_RST)
PRINTFLG("rst");
if (chain->fw_tcpnf & IP_FW_TCPF_RST)
PRINTFLG("!rst");
if (chain->fw_tcpf & IP_FW_TCPF_PSH)
PRINTFLG("psh");
if (chain->fw_tcpnf & IP_FW_TCPF_PSH)
PRINTFLG("!psh");
if (chain->fw_tcpf & IP_FW_TCPF_ACK)
PRINTFLG("ack");
if (chain->fw_tcpnf & IP_FW_TCPF_ACK)
PRINTFLG("!ack");
if (chain->fw_tcpf & IP_FW_TCPF_URG)
PRINTFLG("urg");
if (chain->fw_tcpnf & IP_FW_TCPF_URG)
PRINTFLG("!urg");
}
if (chain->fw_tcpopt || chain->fw_tcpnopt) {
int _opt_printed = 0;
#define PRINTTOPT(x) {if (_opt_printed) printf(",");\
printf(x); _opt_printed = 1;}
printf(" tcpoptions ");
if (chain->fw_tcpopt & IP_FW_TCPOPT_MSS)
PRINTTOPT("mss");
if (chain->fw_tcpnopt & IP_FW_TCPOPT_MSS)
PRINTTOPT("!mss");
if (chain->fw_tcpopt & IP_FW_TCPOPT_WINDOW)
PRINTTOPT("window");
if (chain->fw_tcpnopt & IP_FW_TCPOPT_WINDOW)
PRINTTOPT("!window");
if (chain->fw_tcpopt & IP_FW_TCPOPT_SACK)
PRINTTOPT("sack");
if (chain->fw_tcpnopt & IP_FW_TCPOPT_SACK)
PRINTTOPT("!sack");
if (chain->fw_tcpopt & IP_FW_TCPOPT_TS)
PRINTTOPT("ts");
if (chain->fw_tcpnopt & IP_FW_TCPOPT_TS)
PRINTTOPT("!ts");
if (chain->fw_tcpopt & IP_FW_TCPOPT_CC)
PRINTTOPT("cc");
if (chain->fw_tcpnopt & IP_FW_TCPOPT_CC)
PRINTTOPT("!cc");
}
if (chain->fw_flg & IP_FW_F_ICMPBIT) {
int type_index;
int first = 1;
printf(" icmptype");
for (type_index = 0; type_index < IP_FW_ICMPTYPES_DIM * sizeof(unsigned) * 8; ++type_index)
if (chain->fw_uar.fw_icmptypes[type_index / (sizeof(unsigned) * 8)] &
(1U << (type_index % (sizeof(unsigned) * 8)))) {
printf("%c%d", first == 1 ? ' ' : ',', type_index);
first = 0;
}
}
printf("\n");
done:
if (do_resolv)
endservent();
}
#ifndef _WIN32 /* no queues support yet! */
int
sort_q(const void *pa, const void *pb)
{
int rev = (do_sort < 0);
int field = rev ? -do_sort : do_sort;
long long res = 0;
const struct dn_flow_queue *a = pa;
const struct dn_flow_queue *b = pb;
switch (field) {
case 1: /* pkts */
res = a->len - b->len;
break;
case 2: /* bytes */
res = a->len_bytes - b->len_bytes;
break;
case 3: /* tot pkts */
res = a->tot_pkts - b->tot_pkts;
break;
case 4: /* tot bytes */
res = a->tot_bytes - b->tot_bytes;
break;
}
if (res < 0)
res = -1;
if (res > 0)
res = 1;
return (int)(rev ? res : -res);
}
static void
list_queues(struct dn_flow_set *fs, struct dn_flow_queue *q)
{
int l;
printf(" mask: 0x%02x 0x%08x/0x%04x -> 0x%08x/0x%04x\n",
fs->flow_mask.proto,
fs->flow_mask.src_ip, fs->flow_mask.src_port,
fs->flow_mask.dst_ip, fs->flow_mask.dst_port);
if (fs->rq_elements == 0)
return;
printf("BKT Prot ___Source IP/port____ "
"____Dest. IP/port____ Tot_pkt/bytes Pkt/Byte Drp\n");
if (do_sort != 0)
heapsort(q, fs->rq_elements, sizeof *q, sort_q);
for (l = 0; l < fs->rq_elements; l++) {
struct in_addr ina;
struct protoent *pe;
ina.s_addr = htonl(q[l].id.src_ip);
printf("%3d ", q[l].hash_slot);
pe = getprotobynumber(q[l].id.proto);
if (pe)
printf("%-4s ", pe->p_name);
else
printf("%4u ", q[l].id.proto);
printf("%15s/%-5d ",
inet_ntoa(ina), q[l].id.src_port);
ina.s_addr = htonl(q[l].id.dst_ip);
printf("%15s/%-5d ",
inet_ntoa(ina), q[l].id.dst_port);
printf("%4qu %8qu %2u %4u %3u\n",
q[l].tot_pkts, q[l].tot_bytes,
q[l].len, q[l].len_bytes, q[l].drops);
if (verbose)
printf(" S %20qd F %20qd\n",
q[l].S, q[l].F);
}
}
static void
print_flowset_parms(struct dn_flow_set *fs, char *prefix)
{
int l;
char qs[30];
char plr[30];
char red[90]; /* Display RED parameters */
l = fs->qsize;
if (fs->flags_fs & DN_QSIZE_IS_BYTES) {
if (l >= 8192)
sprintf(qs, "%d KB", l / 1024);
else
sprintf(qs, "%d B", l);
} else
sprintf(qs, "%3d sl.", l);
if (fs->plr)
sprintf(plr, "plr %f", 1.0 * fs->plr / (double)(0x7fffffff));
else
plr[0] = '\0';
if (fs->flags_fs & DN_IS_RED) /* RED parameters */
sprintf(red,
"\n\t %cRED w_q %f min_th %d max_th %d max_p %f",
(fs->flags_fs & DN_IS_GENTLE_RED) ? 'G' : ' ',
1.0 * fs->w_q / (double)(1 << SCALE_RED),
SCALE_VAL(fs->min_th),
SCALE_VAL(fs->max_th),
1.0 * fs->max_p / (double)(1 << SCALE_RED));
else
sprintf(red, "droptail");
printf("%s %s%s %d queues (%d buckets) %s\n",
prefix, qs, plr, fs->rq_elements, fs->rq_size, red);
}
static void
sysctl_handler(int ac, char *av[], int which)
{
ac--;
av++;
if (*av == NULL) {
warnx("missing keyword to enable/disable\n");
} else if (strncmp(*av, "firewall", strlen(*av)) == 0) {
sysctlbyname("net.inet.ip.fw.enable", NULL, 0,
&which, sizeof(which));
} else if (strncmp(*av, "one_pass", strlen(*av)) == 0) {
sysctlbyname("net.inet.ip.fw.one_pass", NULL, 0,
&which, sizeof(which));
} else if (strncmp(*av, "debug", strlen(*av)) == 0) {
sysctlbyname("net.inet.ip.fw.debug", NULL, 0,
&which, sizeof(which));
} else if (strncmp(*av, "verbose", strlen(*av)) == 0) {
sysctlbyname("net.inet.ip.fw.verbose", NULL, 0,
&which, sizeof(which));
} else {
warnx("unrecognize enable/disable keyword: %s\n", *av);
}
}
#endif /* !_WIN32 */
static void
list(int ac, char *av[])
{
struct ip_fw *rules;
struct dn_pipe *pipes;
void *data = NULL;
int pcwidth = 0;
int bcwidth = 0;
int n, num = 0;
int nbytes;
#ifndef _WIN32
/* get rules or pipes from kernel, resizing array as necessary */
{
const int unit = do_pipe ? sizeof(*pipes) : sizeof(*rules);
const int ocmd = do_pipe ? IP_DUMMYNET_GET : IP_FW_GET;
int nalloc = unit;
nbytes = nalloc;
while (nbytes >= nalloc) {
nalloc = nalloc * 2 + 200;
nbytes = nalloc;
if ((data = realloc(data, nbytes)) == NULL)
err(EX_OSERR, "realloc");
if (getsockopt(s, IPPROTO_IP, ocmd, data, &nbytes) < 0)
err(EX_OSERR, "getsockopt(IP_%s_GET)",
do_pipe ? "DUMMYNET" : "FW");
}
}
#else /* !_WIN32 the same code but without pipe support */
{
const int unit = sizeof(*rules);
const int ocmd = IP_FW_GET;
int nalloc = unit;
nbytes = nalloc;
while (nbytes >= nalloc) {
nalloc = nalloc * 2 + 200;
nbytes = nalloc;
if ((data = realloc(data, nbytes)) == NULL)
err(EX_OSERR, "realloc");
if (getsockopt(s, IPPROTO_IP, ocmd, data, &nbytes) < 0)
err(EX_OSERR, "getsockopt(IP_%s_GET)",
"FW");
}
}
#endif /* _WIN32 */
#ifndef _WIN32
/* display requested pipes */
if (do_pipe) {
u_long rulenum;
void *next = data;
struct dn_pipe *p = (struct dn_pipe *) data;
struct dn_flow_set *fs;
struct dn_flow_queue *q;
int l;
if (ac > 0)
rulenum = strtoul(*av++, NULL, 10);
else
rulenum = 0;
for (; nbytes >= sizeof *p; p = (struct dn_pipe *)next) {
double b = p->bandwidth;
char buf[30];
char prefix[80];
if (p->next != (struct dn_pipe *)DN_IS_PIPE)
break;
l = sizeof(*p) + p->fs.rq_elements * sizeof(*q);
next = (void *)p + l;
nbytes -= l;
q = (struct dn_flow_queue *)(p+1);
if (rulenum != 0 && rulenum != p->pipe_nr)
continue;
if (p->if_name[0] != '\0')
sprintf(buf, "%s", p->if_name);
else if (b == 0)
sprintf(buf, "unlimited");
else if (b >= 1000000)
sprintf(buf, "%7.3f Mbit/s", b/1000000);
else if (b >= 1000)
sprintf(buf, "%7.3f Kbit/s", b/1000);
else
sprintf(buf, "%7.3f bit/s ", b);
sprintf(prefix, "%05d: %s %4d ms ",
p->pipe_nr, buf, p->delay);
print_flowset_parms(&(p->fs), prefix);
if (verbose)
printf(" V %20qd\n", p->V >> MY_M);
list_queues(&(p->fs), q);
}
fs = (struct dn_flow_set *) next;
for (; nbytes >= sizeof *fs; fs = (struct dn_flow_set *)next) {
char prefix[80];
if (fs->next != (struct dn_flow_set *)DN_IS_QUEUE)
break;
l = sizeof(*fs) + fs->rq_elements * sizeof(*q);
next = (void *)fs + l;
nbytes -= l;
q = (struct dn_flow_queue *)(fs+1);
sprintf(prefix, "q%05d: weight %d pipe %d ",
fs->fs_nr, fs->weight, fs->parent_nr);
print_flowset_parms(fs, prefix);
list_queues(fs, q);
}
free(data);
return;
}
#endif /* !_WIN32 */
rules = (struct ip_fw *)data;
/* determine num more accurately */
num = 0;
while (rules[num].fw_number < 65535)
num++;
num++; /* counting starts from 0 ... */
/* if showing stats, figure out column widths ahead of time */
if (do_acct) {
for (n = 0; n < num; n++) {
struct ip_fw *const r = &rules[n];
char temp[32];
int width;
/* packet counter */
#ifndef _WIN32
width = sprintf(temp, "%qu", r->fw_pcnt);
#else
width = sprintf(temp, "%I64u", r->fw_pcnt);
#endif
if (width > pcwidth)
pcwidth = width;
/* byte counter */
#ifndef _WIN32
width = sprintf(temp, "%qu", r->fw_bcnt);
#else
width = sprintf(temp, "%I64u", r->fw_bcnt);
#endif
if (width > bcwidth)
bcwidth = width;
}
}
if (ac == 0) {
/* display all rules */
for (n = 0; n < num; n++) {
struct ip_fw *const r = &rules[n];
show_ipfw(r, pcwidth, bcwidth);
}
} else {
/* display specific rules requested on command line */
int exitval = EX_OK;
while (ac--) {
u_long rnum;
char *endptr;
int seen;
/* convert command line rule # */
rnum = strtoul(*av++, &endptr, 10);
if (*endptr) {
exitval = EX_USAGE;
warnx("invalid rule number: %s", *(av - 1));
continue;
}
do_dynamic = 0;
for (seen = n = 0; n < num; n++) {
struct ip_fw *const r = &rules[n];
if (r->fw_number > rnum)
break;
if (r->fw_number == rnum) {
show_ipfw(r, pcwidth, bcwidth);
seen = 1;
}
}
if (!seen) {
/* give precedence to other error(s) */
if (exitval == EX_OK)
exitval = EX_UNAVAILABLE;
warnx("rule %lu does not exist", rnum);
}
}
if (exitval != EX_OK)
exit(exitval);
}
/*
* show dynamic rules
*/
if (do_dynamic && num * sizeof (rules[0]) != nbytes) {
struct ipfw_dyn_rule *d =
(struct ipfw_dyn_rule *)&rules[num];
struct in_addr a;
struct protoent *pe;
printf("## Dynamic rules:\n");
for (;; d++) {
if (d->expire == 0 && !do_expired) {
if (d->next == NULL)
break;
continue;
}
#ifndef _WIN32
printf("%05d %qu %qu (T %d, slot %d)",
#else
printf("%05d %I64u %I64u (T %d, slot %d)",
#endif
(u_short)(d->rule),
d->pcnt, d->bcnt,
d->expire,
d->bucket);
switch (d->dyn_type) {
case DYN_LIMIT_PARENT:
printf(" PARENT %d", d->count);
break;
case DYN_LIMIT:
printf(" LIMIT");
break;
case DYN_KEEP_STATE: /* bidir, no mask */
printf(" <->");
break;
}
pe = getprotobynumber(d->id.proto);
if (pe)
printf(" %s,", pe->p_name);
else
printf(" %u,", d->id.proto);
a.s_addr = htonl(d->id.src_ip);
printf(" %s %d", inet_ntoa(a), d->id.src_port);
a.s_addr = htonl(d->id.dst_ip);
printf("<-> %s %d", inet_ntoa(a), d->id.dst_port);
printf("\n");
if (d->next == NULL)
break;
}
}
free(data);
}
static void
show_usage(void)
{
fprintf(stderr, "usage: ipfw [options]\n"
" [pipe] flush\n"
" add [number] rule\n"
" [pipe] delete number ...\n"
" [pipe] list [number ...]\n"
" [pipe] show [number ...]\n"
" zero [number ...]\n"
" resetlog [number ...]\n"
#ifndef _WIN32
" pipe number config [pipeconfig]\n"
#endif
" rule: [prob <match_probability>] action proto src dst extras...\n"
" action:\n"
" {allow|permit|accept|pass|deny|drop|reject|unreach code|\n"
" reset|count|skipto num|divert port|tee port|fwd ip|\n"
" pipe num} [log [logamount count]]\n"
" proto: {ip|tcp|udp|icmp|<number>}\n"
" src: from [not] {me|any|ip[{/bits|:mask}]} [{port[-port]}, [port], ...]\n"
" dst: to [not] {me|any|ip[{/bits|:mask}]} [{port[-port]}, [port], ...]\n"
" extras:\n"
#ifndef _WIN32
" uid {user id}\n"
" gid {group id}\n"
#endif
" fragment (may not be used with ports or tcpflags)\n"
" in\n"
" out\n"
" {xmit|recv|via} {iface|ip|any}\n"
" {established|setup}\n"
" tcpflags [!]{syn|fin|rst|ack|psh|urg}, ...\n"
" ipoptions [!]{ssrr|lsrr|rr|ts}, ...\n"
" tcpoptions [!]{mss|window|sack|ts|cc}, ...\n"
" icmptypes {type[, type]}...\n"
" keep-state [method]\n"
#ifndef _WIN32
" pipeconfig:\n"
" {bw|bandwidth} <number>{bit/s|Kbit/s|Mbit/s|Bytes/s|KBytes/s|MBytes/s}\n"
" {bw|bandwidth} interface_name\n"
" delay <milliseconds>\n"
" queue <size>{packets|Bytes|KBytes}\n"
" plr <fraction>\n"
" mask {all| [dst-ip|src-ip|dst-port|src-port|proto] <number>}\n"
" buckets <number>}\n"
" {red|gred} <fraction>/<number>/<number>/<fraction>\n"
" droptail\n"
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -