📄 ipfw.c.svn-base
字号:
#endif
);
exit(EX_USAGE);
}
static int
lookup_host (char *host, struct in_addr *ipaddr)
{
struct hostent *he;
if (!inet_aton(host, ipaddr)) {
if ((he = gethostbyname(host)) == NULL)
return(-1);
*ipaddr = *(struct in_addr *)he->h_addr_list[0];
}
return(0);
}
static void
fill_ip(struct in_addr *ipno, struct in_addr *mask, int *acp, char ***avp)
{
int ac = *acp;
char **av = *avp;
char *p = 0, md = 0;
if (ac && !strncmp(*av, "any", strlen(*av))) {
ipno->s_addr = mask->s_addr = 0; av++; ac--;
} else {
p = strchr(*av, '/');
if (!p)
p = strchr(*av, ':');
if (p) {
md = *p;
*p++ = '\0';
}
if (lookup_host(*av, ipno) != 0)
errx(EX_NOHOST, "hostname ``%s'' unknown", *av);
switch (md) {
case ':':
if (!inet_aton(p, mask))
errx(EX_DATAERR, "bad netmask ``%s''", p);
break;
case '/':
if (atoi(p) == 0) {
mask->s_addr = 0;
} else if (atoi(p) > 32) {
errx(EX_DATAERR, "bad width ``%s''", p);
} else {
mask->s_addr =
htonl(~0 << (32 - atoi(p)));
}
break;
default:
mask->s_addr = htonl(~0);
break;
}
ipno->s_addr &= mask->s_addr;
av++;
ac--;
}
*acp = ac;
*avp = av;
}
static void
fill_reject_code(u_short *codep, char *str)
{
struct icmpcode *ic;
u_long val;
char *s;
if (str == '\0')
errx(EX_DATAERR, "missing unreachable code");
val = strtoul(str, &s, 0);
if (s != str && *s == '\0' && val < 0x100) {
*codep = val;
return;
}
for (ic = icmpcodes; ic->str; ic++)
if (!strcasecmp(str, ic->str)) {
*codep = ic->code;
return;
}
errx(EX_DATAERR, "unknown ICMP unreachable code ``%s''", str);
}
static void
add_port(u_short *cnt, u_short *ptr, u_short off, u_short port)
{
if (off + *cnt >= IP_FW_MAX_PORTS)
errx(EX_USAGE, "too many ports (max is %d)", IP_FW_MAX_PORTS);
ptr[off+*cnt] = port;
(*cnt)++;
}
static int
lookup_port(const char *arg, int proto, int test, int nodash)
{
int val;
char *earg, buf[32];
struct servent *s;
char *p, *q;
snprintf(buf, sizeof(buf), "%s", arg);
for (p = q = buf; *p; *q++ = *p++) {
if (*p == '\\') {
if (*(p+1))
p++;
} else {
if (*p == ',' || (nodash && *p == '-'))
break;
}
}
*q = '\0';
val = (int) strtoul(buf, &earg, 0);
if (!*buf || *earg) {
char *protocol = NULL;
if (proto != 0) {
struct protoent *pe = getprotobynumber(proto);
if (pe)
protocol = pe->p_name;
}
setservent(1);
if ((s = getservbyname(buf, protocol))) {
val = htons(s->s_port);
} else {
if (!test)
errx(EX_DATAERR, "unknown port ``%s''", buf);
val = -1;
}
} else {
if (val < 0 || val > 0xffff) {
if (!test)
errx(EX_DATAERR,
"port ``%s'' out of range", buf);
val = -1;
}
}
return(val);
}
/*
* return: 0 normally, 1 if first pair is a range,
* 2 if first pair is a port+mask
*/
static int
fill_port(u_short *cnt, u_short *ptr, u_short off, char *arg, int proto)
{
char *s;
int initial_range = 0;
for (s = arg; *s && *s != ',' && *s != '-' && *s != ':'; s++) {
if (*s == '\\' && *(s+1))
s++;
}
if (*s == ':') {
*s++ = '\0';
if (strchr(arg, ','))
errx(EX_USAGE, "port/mask must be first in list");
add_port(cnt, ptr, off,
*arg ? lookup_port(arg, proto, 0, 0) : 0x0000);
arg = s;
s = strchr(arg, ',');
if (s)
*s++ = '\0';
add_port(cnt, ptr, off,
*arg ? lookup_port(arg, proto, 0, 0) : 0xffff);
arg = s;
initial_range = 2;
} else
if (*s == '-') {
*s++ = '\0';
if (strchr(arg, ','))
errx(EX_USAGE, "port range must be first in list");
add_port(cnt, ptr, off,
*arg ? lookup_port(arg, proto, 0, 0) : 0x0000);
arg = s;
s = strchr(arg, ',');
if (s)
*s++ = '\0';
add_port(cnt, ptr, off,
*arg ? lookup_port(arg, proto, 0, 0) : 0xffff);
arg = s;
initial_range = 1;
}
while (arg != NULL) {
s = strchr(arg, ',');
if (s)
*s++ = '\0';
add_port(cnt, ptr, off, lookup_port(arg, proto, 0, 0));
arg = s;
}
return initial_range;
}
static void
fill_tcpflag(u_char *set, u_char *reset, char **vp)
{
char *p = *vp, *q;
u_char *d;
while (p && *p) {
struct tpcflags {
char * name;
u_char value;
} flags[] = {
{ "syn", IP_FW_TCPF_SYN },
{ "fin", IP_FW_TCPF_FIN },
{ "ack", IP_FW_TCPF_ACK },
{ "psh", IP_FW_TCPF_PSH },
{ "rst", IP_FW_TCPF_RST },
{ "urg", IP_FW_TCPF_URG }
};
int i;
if (*p == '!') {
p++;
d = reset;
} else {
d = set;
}
q = strchr(p, ',');
if (q)
*q++ = '\0';
for (i = 0; i < sizeof(flags) / sizeof(flags[0]); ++i)
if (!strncmp(p, flags[i].name, strlen(p))) {
*d |= flags[i].value;
break;
}
if (i == sizeof(flags) / sizeof(flags[0]))
errx(EX_DATAERR, "invalid tcp flag ``%s''", p);
p = q;
}
}
static void
fill_tcpopts(u_char *set, u_char *reset, char **vp)
{
char *p = *vp, *q;
u_char *d;
while (p && *p) {
struct tpcopts {
char * name;
u_char value;
} opts[] = {
{ "mss", IP_FW_TCPOPT_MSS },
{ "window", IP_FW_TCPOPT_WINDOW },
{ "sack", IP_FW_TCPOPT_SACK },
{ "ts", IP_FW_TCPOPT_TS },
{ "cc", IP_FW_TCPOPT_CC },
};
int i;
if (*p == '!') {
p++;
d = reset;
} else {
d = set;
}
q = strchr(p, ',');
if (q)
*q++ = '\0';
for (i = 0; i < sizeof(opts) / sizeof(opts[0]); ++i)
if (!strncmp(p, opts[i].name, strlen(p))) {
*d |= opts[i].value;
break;
}
if (i == sizeof(opts) / sizeof(opts[0]))
errx(EX_DATAERR, "invalid tcp option ``%s''", p);
p = q;
}
}
static void
fill_ipopt(u_char *set, u_char *reset, char **vp)
{
char *p = *vp, *q;
u_char *d;
while (p && *p) {
if (*p == '!') {
p++;
d = reset;
} else {
d = set;
}
q = strchr(p, ',');
if (q)
*q++ = '\0';
if (!strncmp(p, "ssrr", strlen(p))) *d |= IP_FW_IPOPT_SSRR;
if (!strncmp(p, "lsrr", strlen(p))) *d |= IP_FW_IPOPT_LSRR;
if (!strncmp(p, "rr", strlen(p))) *d |= IP_FW_IPOPT_RR;
if (!strncmp(p, "ts", strlen(p))) *d |= IP_FW_IPOPT_TS;
p = q;
}
}
static void
fill_icmptypes(unsigned *types, char **vp, u_int *fw_flg)
{
unsigned long icmptype;
char *c = *vp;
while (*c) {
if (*c == ',')
++c;
icmptype = strtoul(c, &c, 0);
if (*c != ',' && *c != '\0')
errx(EX_DATAERR, "invalid ICMP type");
if (icmptype >= IP_FW_ICMPTYPES_DIM * sizeof(unsigned) * 8)
errx(EX_DATAERR, "ICMP type out of range");
types[icmptype / (sizeof(unsigned) * 8)] |=
1 << (icmptype % (sizeof(unsigned) * 8));
*fw_flg |= IP_FW_F_ICMPBIT;
}
}
static void
delete(int ac, char *av[])
{
struct ip_fw rule;
#ifndef _WIN32
struct dn_pipe pipe;
#endif
int i;
int exitval = EX_OK;
memset(&rule, 0, sizeof rule);
#ifndef _WIN32
memset(&pipe, 0, sizeof pipe);
#endif
av++; ac--;
/* Rule number */
while (ac && isdigit(**av)) {
i = atoi(*av); av++; ac--;
#ifndef _WIN32
if (do_pipe) {
if (do_pipe == 1)
pipe.pipe_nr = i;
else
pipe.fs.fs_nr = i;
i = setsockopt(s, IPPROTO_IP, IP_DUMMYNET_DEL,
&pipe, sizeof pipe);
if (i) {
exitval = 1;
warn("rule %u: setsockopt(IP_DUMMYNET_DEL)",
do_pipe == 1 ? pipe.pipe_nr :
pipe.fs.fs_nr);
}
} else {
#endif /* !_WIN32 */
rule.fw_number = i;
i = setsockopt(s, IPPROTO_IP, IP_FW_DEL, &rule,
sizeof rule);
if (i) {
exitval = EX_UNAVAILABLE;
warn("rule %u: setsockopt(IP_FW_DEL)",
rule.fw_number);
}
#ifndef _WIN32
}
#endif
}
if (exitval != EX_OK)
exit(exitval);
}
static void
verify_interface(union ip_fw_if *ifu)
{
struct ifreq ifr;
/*
* If a unit was specified, check for that exact interface.
* If a wildcard was specified, check for unit 0.
*/
snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s%d",
ifu->fu_via_if.name,
ifu->fu_via_if.unit == -1 ? 0 : ifu->fu_via_if.unit);
if (ioctl(s, SIOCGIFFLAGS, &ifr) < 0)
warnx("warning: interface ``%s'' does not exist",
ifr.ifr_name);
}
static void
fill_iface(char *which, union ip_fw_if *ifu, int *byname, int ac, char *arg)
{
if (!ac)
errx(EX_USAGE, "missing argument for ``%s''", which);
/* Parse the interface or address */
if (!strcmp(arg, "any")) {
ifu->fu_via_ip.s_addr = 0;
*byname = 0;
} else if (!isdigit(*arg)) {
char *q;
*byname = 1;
strncpy(ifu->fu_via_if.name, arg,
sizeof(ifu->fu_via_if.name));
ifu->fu_via_if.name[sizeof(ifu->fu_via_if.name) - 1] = '\0';
for (q = ifu->fu_via_if.name;
*q && !isdigit(*q) && *q != '*'; q++)
continue;
ifu->fu_via_if.unit = (*q == '*') ? -1 : atoi(q);
*q = '\0';
verify_interface(ifu);
} else if (!inet_aton(arg, &ifu->fu_via_ip)) {
errx(EX_DATAERR, "bad ip address ``%s''", arg);
} else
*byname = 0;
}
#ifndef _WIN32
static void
config_pipe(int ac, char **av)
{
struct dn_pipe pipe;
int i;
char *end;
memset(&pipe, 0, sizeof pipe);
av++; ac--;
/* Pipe number */
if (ac && isdigit(**av)) {
i = atoi(*av); av++; ac--;
if (do_pipe == 1)
pipe.pipe_nr = i;
else
pipe.fs.fs_nr = i;
}
while (ac > 1) {
if (!strncmp(*av, "plr", strlen(*av))) {
double d = strtod(av[1], NULL);
if (d > 1)
d = 1;
else if (d < 0)
d = 0;
pipe.fs.plr = (int)(d*0x7fffffff);
av += 2;
ac -= 2;
} else if (!strncmp(*av, "queue", strlen(*av))) {
end = NULL;
pipe.fs.qsize = strtoul(av[1], &end, 0);
if (*end == 'K' || *end == 'k') {
pipe.fs.flags_fs |= DN_QSIZE_IS_BYTES;
pipe.fs.qsize *= 1024;
} else if (*end == 'B' || !strncmp(end, "by", 2)) {
pipe.fs.flags_fs |= DN_QSIZE_IS_BYTES;
}
av += 2;
ac -= 2;
} else if (!strncmp(*av, "buckets", strlen(*av))) {
pipe.fs.rq_size = strtoul(av[1], NULL, 0);
av += 2;
ac -= 2;
} else if (!strncmp(*av, "mask", strlen(*av))) {
/* per-flow queue, mask is dst_ip, dst_port,
* src_ip, src_port, proto measured in bits
*/
u_int32_t a;
void *par = NULL;
pipe.fs.flow_mask.dst_ip = 0;
pipe.fs.flow_mask.src_ip = 0;
pipe.fs.flow_mask.dst_port = 0;
pipe.fs.flow_mask.src_port = 0;
pipe.fs.flow_mask.proto = 0;
end = NULL;
av++; ac--;
if (ac >= 1 && !strncmp(*av, "all", strlen(*av))) {
/* special case -- all bits are significant */
pipe.fs.flow_mask.dst_ip = ~0;
pipe.fs.flow_mask.src_ip = ~0;
pipe.fs.flow_mask.dst_port = ~0;
pipe.fs.flow_mask.src_port = ~0;
pipe.fs.flow_mask.proto = ~0;
pipe.fs.flags_fs |= DN_HAVE_FLOW_MASK;
av++;
ac--;
continue;
}
while (ac >= 1) {
int len = strlen(*av);
if (!strncmp(*av, "dst-ip", len))
par = &pipe.fs.flow_mask.dst_ip;
else if (!strncmp(*av, "src-ip", len))
par = &pipe.fs.flow_mask.src_ip;
else if (!strncmp(*av, "dst-port", len))
par = &pipe.fs.flow_mask.dst_port;
else if (!strncmp(*av, "src-port", len))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -