⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ipfw.c.svn-base

📁 wipfw 是windows下的网络控制工具
💻 SVN-BASE
📖 第 1 页 / 共 5 页
字号:
					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 + -