patch-pre2.0.7 linux/net/ipv4/ip_fw.c
Next file: linux/net/ipv4/ip_input.c
Previous file: linux/net/ipv4/ip_forward.c
Back to the patch index
Back to the overall index
- Lines: 349
- Date:
Sun May 19 23:40:50 1996
- Orig file:
pre2.0.6/linux/net/ipv4/ip_fw.c
- Orig date:
Fri Apr 12 15:52:12 1996
diff -u --recursive --new-file pre2.0.6/linux/net/ipv4/ip_fw.c linux/net/ipv4/ip_fw.c
@@ -33,6 +33,10 @@
* Jos Vos <jos@xos.nl> 8/2/1996.
* Add support for matching on device names.
* Jos Vos <jos@xos.nl> 15/2/1996.
+ * Transparent proxying support.
+ * Willy Konynenberg <willy@xos.nl> 10/5/96.
+ * Make separate accounting on incoming and outgoing packets possible.
+ * Jos Vos <jos@xos.nl> 18/5/1996.
*
*
* Masquerading functionality
@@ -186,17 +190,18 @@
/*
- * Returns 0 if packet should be dropped, 1 if it should be accepted,
- * and -1 if an ICMP host unreachable packet should be sent.
+ * Returns one of the generic firewall policies, like FW_ACCEPT.
* Also does accounting so you can feed it the accounting chain.
- * If opt is set to 1, it means that we do this for accounting
- * purposes (searches all entries and handles fragments different).
- * If opt is set to 2, it doesn't count a matching packet, which
- * is used when calling this for checking purposes (IP_FW_CHK_*).
+ *
+ * The modes is either IP_FW_MODE_FW (normal firewall mode),
+ * IP_FW_MODE_ACCT_IN or IP_FW_MODE_ACCT_OUT (accounting mode,
+ * steps through the entire chain and handles fragments
+ * differently), or IP_FW_MODE_CHK (handles user-level check,
+ * counters are not updated).
*/
-int ip_fw_chk(struct iphdr *ip, struct device *rif, struct ip_fw *chain, int policy, int opt)
+int ip_fw_chk(struct iphdr *ip, struct device *rif, __u16 *redirport, struct ip_fw *chain, int policy, int mode)
{
struct ip_fw *f;
struct tcphdr *tcp=(struct tcphdr *)((unsigned long *)ip+ip->ihl);
@@ -245,8 +250,9 @@
if (offset == 1 && ip->protocol == IPPROTO_TCP)
return FW_BLOCK;
- if (offset!=0 && (opt != 1) && (ip->protocol == IPPROTO_TCP ||
- ip->protocol == IPPROTO_UDP || ip->protocol == IPPROTO_ICMP))
+ if (offset!=0 && !(mode & (IP_FW_MODE_ACCT_IN|IP_FW_MODE_ACCT_OUT)) &&
+ (ip->protocol == IPPROTO_TCP || ip->protocol == IPPROTO_UDP ||
+ ip->protocol == IPPROTO_ICMP))
return FW_ACCEPT;
/*
@@ -358,37 +364,43 @@
/* reverse direction */
match |= 0x02;
- if (match)
- {
- /*
- * Look for a VIA address match
- */
- if(f->fw_via.s_addr && rif)
- {
- if(rif->pa_addr!=f->fw_via.s_addr)
- continue; /* Mismatch */
- }
+ if (!match)
+ continue;
- /*
- * Look for a VIA device match
- */
- if(f->fw_viadev)
- {
- if(rif!=f->fw_viadev)
- continue; /* Mismatch */
- }
+ /*
+ * Look for a VIA address match
+ */
+ if(f->fw_via.s_addr && rif)
+ {
+ if(rif->pa_addr!=f->fw_via.s_addr)
+ continue; /* Mismatch */
+ }
- /*
- * Drop through - this is a match
- */
+ /*
+ * Look for a VIA device match
+ */
+ if(f->fw_viadev)
+ {
+ if(rif!=f->fw_viadev)
+ continue; /* Mismatch */
}
- else
- continue;
/*
* Ok the chain addresses match.
*/
+#ifdef CONFIG_IP_ACCT
+ /*
+ * See if we're in accounting mode and only want to
+ * count incoming or outgoing packets.
+ */
+
+ if (mode & (IP_FW_MODE_ACCT_IN|IP_FW_MODE_ACCT_OUT) &&
+ ((mode == IP_FW_MODE_ACCT_IN && f->fw_flg&IP_FW_F_ACCTOUT) ||
+ (mode == IP_FW_MODE_ACCT_OUT && f->fw_flg&IP_FW_F_ACCTIN)))
+ continue;
+
+#endif
f_prt=f->fw_flg&IP_FW_F_KIND;
if (f_prt!=IP_FW_F_ALL)
{
@@ -429,6 +441,7 @@
continue;
}
}
+
#ifdef CONFIG_IP_FIREWALL_VERBOSE
/*
* VERY ugly piece of code which actually
@@ -437,53 +450,72 @@
if (f->fw_flg & IP_FW_F_PRN)
{
- if(opt != 1) {
+ __u32 *opt = (__u32 *) (ip + 1);
+ int opti;
+
+ if(mode == IP_FW_MODE_ACCT_IN)
+ printk(KERN_INFO "IP acct in ");
+ else if(mode == IP_FW_MODE_ACCT_OUT)
+ printk(KERN_INFO "IP acct out ");
+ else {
+ if(chain == ip_fw_fwd_chain)
+ printk(KERN_INFO "IP fw-fwd ");
+ else if(chain == ip_fw_in_chain)
+ printk(KERN_INFO "IP fw-in ");
+ else
+ printk(KERN_INFO "IP fw-out ");
if(f->fw_flg&IP_FW_F_ACCEPT) {
- if(f->fw_flg&IP_FW_F_MASQ)
- printk("masq ");
+ if(f->fw_flg&IP_FW_F_REDIR)
+ printk("acc/r%d ", f->fw_pts[f->fw_nsp+f->fw_ndp]);
+ else if(f->fw_flg&IP_FW_F_MASQ)
+ printk("acc/masq ");
else
- printk("acc ");
+ printk("acc ");
} else if(f->fw_flg&IP_FW_F_ICMPRPL)
- printk("rej ");
+ printk("rej ");
else
printk("deny ");
}
- if (rif)
- printk("%s ", rif->name);
+ printk(rif ? rif->name : "-");
switch(ip->protocol)
{
case IPPROTO_TCP:
- printk("TCP ");
+ printk(" TCP ");
break;
case IPPROTO_UDP:
- printk("UDP ");
+ printk(" UDP ");
break;
case IPPROTO_ICMP:
- printk("ICMP:%d ", icmp_type);
+ printk(" ICMP/%d ", icmp_type);
break;
default:
- printk("p=%d ",ip->protocol);
+ printk(" PROTO=%d ", ip->protocol);
break;
}
print_ip(ip->saddr);
if(ip->protocol == IPPROTO_TCP || ip->protocol == IPPROTO_UDP)
- printk(":%d", src_port);
+ printk(":%hu", src_port);
printk(" ");
print_ip(ip->daddr);
if(ip->protocol == IPPROTO_TCP || ip->protocol == IPPROTO_UDP)
- printk(":%d",dst_port);
+ printk(":%hu", dst_port);
+ printk(" L=%hu S=0x%2.2hX I=%hu F=0x%4.4hX T=%hu",
+ ntohs(ip->tot_len), ip->tos, ntohs(ip->id),
+ ip->frag_off, ip->ttl);
+ for (opti = 0; opti < (ip->ihl - sizeof(struct iphdr) / 4); opti++)
+ printk(" O=0x%8.8X", *opt++);
printk("\n");
}
#endif
- if (opt != 2) {
+ if (mode != IP_FW_MODE_CHK) {
f->fw_bcnt+=ntohs(ip->tot_len);
f->fw_pcnt++;
}
- if (opt != 1)
+ if (!(mode & (IP_FW_MODE_ACCT_IN|IP_FW_MODE_ACCT_OUT)))
break;
} /* Loop */
- if (opt != 1) {
+ if (!(mode & (IP_FW_MODE_ACCT_IN|IP_FW_MODE_ACCT_OUT))) {
/*
* We rely on policy defined in the rejecting entry or, if no match
@@ -506,7 +538,20 @@
ip->tos = (old_tos & tosand) ^ tosxor;
if (ip->tos != old_tos)
ip_send_check(ip);
- answer=(policy&IP_FW_F_MASQ)?FW_MASQUERADE:FW_ACCEPT;
+#ifdef CONFIG_IP_TRANSPARENT_PROXY
+ if (policy&IP_FW_F_REDIR) {
+ if (redirport)
+ *redirport = htons(f->fw_pts[f->fw_nsp+f->fw_ndp]);
+ answer = FW_REDIRECT;
+ } else
+#endif
+#ifdef CONFIG_IP_MASQUERADE
+ if (policy&IP_FW_F_MASQ)
+ answer = FW_MASQUERADE;
+ else
+#endif
+ answer = FW_ACCEPT;
+
} else if(policy&IP_FW_F_ICMPRPL)
answer = FW_REJECT;
else
@@ -735,6 +780,24 @@
return(NULL);
}
+#ifndef CONFIG_IP_TRANSPARENT_PROXY
+ if (frwl->fw_flg & IP_FW_F_REDIR) {
+#ifdef DEBUG_CONFIG_IP_FIREWALL
+ printk("ip_fw_ctl: unsupported flag IP_FW_F_REDIR\n");
+#endif
+ return(NULL);
+ }
+#endif
+
+#ifndef CONFIG_IP_MASQUERADE
+ if (frwl->fw_flg & IP_FW_F_MASQ) {
+#ifdef DEBUG_CONFIG_IP_FIREWALL
+ printk("ip_fw_ctl: unsupported flag IP_FW_F_MASQ\n");
+#endif
+ return(NULL);
+ }
+#endif
+
if ( (frwl->fw_flg & IP_FW_F_SRNG) && frwl->fw_nsp < 2 )
{
#ifdef DEBUG_CONFIG_IP_FIREWALL
@@ -753,7 +816,7 @@
return(NULL);
}
- if ( frwl->fw_nsp + frwl->fw_ndp > IP_FW_MAX_PORTS )
+ if ( frwl->fw_nsp + frwl->fw_ndp > (frwl->fw_flg & IP_FW_F_REDIR ? IP_FW_MAX_PORTS - 1 : IP_FW_MAX_PORTS) )
{
#ifdef DEBUG_CONFIG_IP_FIREWALL
printk("ip_fw_ctl: too many ports (%d+%d)\n",
@@ -770,14 +833,6 @@
#ifdef CONFIG_IP_ACCT
-#if 0
-void ip_acct_cnt(struct iphdr *iph, struct device *dev, struct ip_fw *f)
-{
- (void) ip_fw_chk(iph, dev, f, 0, 1);
- return;
-}
-#endif
-
int ip_acct_ctl(int stage, void *m, int len)
{
if ( stage == IP_ACCT_FLUSH )
@@ -826,7 +881,7 @@
#ifdef CONFIG_IP_FIREWALL
int ip_fw_ctl(int stage, void *m, int len)
{
- int ret, cmd, fwtype;
+ int cmd, fwtype;
cmd = stage & IP_FW_COMMAND;
fwtype = (stage & IP_FW_TYPE) >> IP_FW_SHIFT;
@@ -888,15 +943,20 @@
return(EINVAL);
}
- if ((ret = ip_fw_chk(ip, viadev, *chains[fwtype],
- *policies[fwtype], 2)) == FW_ACCEPT)
- return(0);
- else if (ret == FW_MASQUERADE)
- return(ECONNRESET);
- else if (ret == FW_REJECT)
- return(ECONNREFUSED);
- else /* ret == FW_BLOCK */
- return(ETIMEDOUT);
+ switch (ip_fw_chk(ip, viadev, NULL, *chains[fwtype],
+ *policies[fwtype], IP_FW_MODE_CHK))
+ {
+ case FW_ACCEPT:
+ return(0);
+ case FW_REDIRECT:
+ return(ECONNABORTED);
+ case FW_MASQUERADE:
+ return(ECONNRESET);
+ case FW_REJECT:
+ return(ECONNREFUSED);
+ default: /* FW_BLOCK */
+ return(ETIMEDOUT);
+ }
}
if ( cmd == IP_FW_MASQ_TIMEOUTS )
@@ -1104,19 +1164,19 @@
* Interface to the generic firewall chains.
*/
-int ipfw_input_check(struct firewall_ops *this, int pf, struct device *dev, void *phdr)
+int ipfw_input_check(struct firewall_ops *this, int pf, struct device *dev, void *phdr, void *arg)
{
- return ip_fw_chk(phdr, dev, ip_fw_in_chain, ip_fw_in_policy, 0);
+ return ip_fw_chk(phdr, dev, arg, ip_fw_in_chain, ip_fw_in_policy, IP_FW_MODE_FW);
}
-int ipfw_output_check(struct firewall_ops *this, int pf, struct device *dev, void *phdr)
+int ipfw_output_check(struct firewall_ops *this, int pf, struct device *dev, void *phdr, void *arg)
{
- return ip_fw_chk(phdr, dev, ip_fw_out_chain, ip_fw_out_policy, 0);
+ return ip_fw_chk(phdr, dev, arg, ip_fw_out_chain, ip_fw_out_policy, IP_FW_MODE_FW);
}
-int ipfw_forward_check(struct firewall_ops *this, int pf, struct device *dev, void *phdr)
+int ipfw_forward_check(struct firewall_ops *this, int pf, struct device *dev, void *phdr, void *arg)
{
- return ip_fw_chk(phdr, dev, ip_fw_fwd_chain, ip_fw_fwd_policy, 0);
+ return ip_fw_chk(phdr, dev, arg, ip_fw_fwd_chain, ip_fw_fwd_policy, IP_FW_MODE_FW);
}
struct firewall_ops ipfw_ops=
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov
with Sam's (original) version of this