summaryrefslogtreecommitdiffstats
path: root/sys/netinet/ip_fw.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netinet/ip_fw.c')
-rw-r--r--sys/netinet/ip_fw.c126
1 files changed, 89 insertions, 37 deletions
diff --git a/sys/netinet/ip_fw.c b/sys/netinet/ip_fw.c
index c8b34ff..4308250 100644
--- a/sys/netinet/ip_fw.c
+++ b/sys/netinet/ip_fw.c
@@ -12,7 +12,7 @@
*
* This software is provided ``AS IS'' without any warranties of any kind.
*
- * $Id: ip_fw.c,v 1.43 1996/06/29 03:33:20 alex Exp $
+ * $Id: ip_fw.c,v 1.44 1996/07/09 20:49:38 nate Exp $
*/
/*
@@ -32,11 +32,13 @@
#include <sys/time.h>
#include <sys/sysctl.h>
#include <net/if.h>
+#include <net/route.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
+#include <netinet/ip_var.h>
#include <netinet/ip_icmp.h>
#include <netinet/ip_fw.h>
@@ -88,7 +90,7 @@ static ip_fw_ctl_t *old_ctl_ptr;
#endif
static int ip_fw_chk __P((struct ip **pip, int hlen, struct ifnet *rif,
- int dir, struct mbuf **m));
+ int dirport, struct mbuf **m));
static int ip_fw_ctl __P((int stage, struct mbuf **mm));
@@ -257,11 +259,24 @@ ipfw_report(char *txt, int rule, struct ip *ip, int counter)
}
/*
- * Returns 1 if it should be accepted, 0 otherwise.
+ * We overload the "dirport" parameter:
+ *
+ * If dirport is negative, packet is outgoing; otherwise incoming.
+ * The low order 16 bits of dirport, if non-zero, indicate that
+ * we should ignore all ``divert <port>'' rules, where <port> is
+ * the low order 16 bits.
+ *
+ * Return value:
+ *
+ * -1 The packet was denied/rejected and has been dropped
+ * 0 The packet is to be accepted; route normally
+ * <port> Divert the packet to divert <port>, if any socket
+ * is bound to it; otherwise just drop it.
*/
static int
-ip_fw_chk(struct ip **pip, int hlen, struct ifnet *rif, int dir, struct mbuf **m)
+ip_fw_chk(struct ip **pip, int hlen,
+ struct ifnet *rif, int dirport, struct mbuf **m)
{
struct ip_fw_chain *chain;
register struct ip_fw *f = NULL;
@@ -284,7 +299,7 @@ ip_fw_chk(struct ip **pip, int hlen, struct ifnet *rif, int dir, struct mbuf **m
++frag_counter;
ipfw_report("Refuse", -1, ip, frag_counter);
m_freem(*m);
- return 0;
+ return -1;
}
src = ip->ip_src;
@@ -331,11 +346,11 @@ ip_fw_chk(struct ip **pip, int hlen, struct ifnet *rif, int dir, struct mbuf **m
f = chain->rule;
/* Check direction inbound */
- if (!dir && !(f->fw_flg & IP_FW_F_IN))
+ if (dirport >= 0 && !(f->fw_flg & IP_FW_F_IN))
continue;
/* Check direction outbound */
- if (dir && !(f->fw_flg & IP_FW_F_OUT))
+ if (dirport < 0 && !(f->fw_flg & IP_FW_F_OUT))
continue;
/* Fragments */
@@ -437,41 +452,65 @@ got_match:
f->fw_bcnt+=ip->ip_len;
f->timestamp = time.tv_sec;
if (f->fw_flg & IP_FW_F_PRN) {
- if (f->fw_flg & IP_FW_F_ACCEPT)
- ipfw_report("Allow", f->fw_number, ip, f->fw_pcnt);
- else if (f->fw_flg & IP_FW_F_COUNT)
- ipfw_report("Count", f->fw_number, ip, f->fw_pcnt);
- else
- ipfw_report("Deny", f->fw_number, ip, f->fw_pcnt);
+ if ((f->fw_flg & IP_FW_F_COMMAND) == IP_FW_F_ACCEPT) {
+ ipfw_report("Accept",
+ f->fw_number, ip, f->fw_pcnt);
+ } else if ((f->fw_flg & IP_FW_F_COMMAND)
+ == IP_FW_F_DIVERT) {
+ if (f->fw_divert_port != (dirport & 0xffff))
+ ipfw_report("Divert", f->fw_number,
+ ip, f->fw_pcnt);
+ } else if ((f->fw_flg & IP_FW_F_COMMAND)
+ == IP_FW_F_COUNT) {
+ ipfw_report("Count",
+ f->fw_number, ip, f->fw_pcnt);
+ } else {
+ ipfw_report("Deny",
+ f->fw_number, ip, f->fw_pcnt);
+ }
}
- if (f->fw_flg & IP_FW_F_ACCEPT)
- return 1;
- if (f->fw_flg & IP_FW_F_COUNT)
- continue;
- break;
+ /* Take appropriate action */
+ if ((f->fw_flg & IP_FW_F_COMMAND) == IP_FW_F_ACCEPT) {
+ return 0;
+ } else if ((f->fw_flg & IP_FW_F_COMMAND) == IP_FW_F_COUNT) {
+ continue;
+ } else if ((f->fw_flg & IP_FW_F_COMMAND) == IP_FW_F_DIVERT) {
+ if (f->fw_divert_port == (dirport & 0xffff))
+ continue; /* ignore this rule */
+ return (f->fw_divert_port);
+ } else
+ break; /* ie, deny/reject */
}
+#ifdef DIAGNOSTIC
+ if (!chain) /* rule 65535 should always be there */
+ panic("ip_fw: chain");
+ if (!f)
+ panic("ip_fw: entry");
+#endif
+
/*
- * Don't icmp outgoing packets at all
+ * At this point, we're going to drop the packet.
+ * Send an ICMP only if all of the following are true:
+ *
+ * - The packet is an incoming packet
+ * - The packet matched a deny rule
+ * - The packet is not an ICMP packet
+ * - The rule has the special ICMP reply flag set
*/
- if (f != NULL && !dir) {
- /*
- * Do not ICMP reply to icmp packets....:) or to packets
- * rejected by entry without the special ICMP reply flag.
- */
- if ((f_prt != IP_FW_F_ICMP) && (f->fw_flg & IP_FW_F_ICMPRPL)) {
- if (f_prt == IP_FW_F_ALL)
- icmp_error(*m, ICMP_UNREACH,
- ICMP_UNREACH_HOST, 0L, 0);
- else
- icmp_error(*m, ICMP_UNREACH,
- ICMP_UNREACH_PORT, 0L, 0);
- return 0;
- }
+ if (dirport >= 0
+ && (f->fw_flg & IP_FW_F_COMMAND) == IP_FW_F_DENY
+ && (f_prt != IP_FW_F_ICMP)
+ && (f->fw_flg & IP_FW_F_ICMPRPL)) {
+ if (f_prt == IP_FW_F_ALL)
+ icmp_error(*m, ICMP_UNREACH, ICMP_UNREACH_HOST, 0L, 0);
+ else
+ icmp_error(*m, ICMP_UNREACH, ICMP_UNREACH_PORT, 0L, 0);
+ return -1;
}
m_freem(*m);
- return 0;
+ return -1;
}
static int
@@ -659,6 +698,13 @@ check_ipfw_struct(struct mbuf *m)
dprintf(("ip_fw_ctl: rule never matches\n"));
return(NULL);
}
+
+ /* Diverting to port zero is illegal */
+ if ((frwl->fw_flg & IP_FW_F_COMMAND) == IP_FW_F_DIVERT
+ && frwl->fw_divert_port == 0) {
+ dprintf(("ip_fw_ctl: can't divert to port 0\n"));
+ return (NULL);
+ }
return frwl;
}
@@ -742,15 +788,21 @@ ip_fw_init(void)
deny.fw_flg = IP_FW_F_ALL;
deny.fw_number = (u_short)-1;
add_entry(&ip_fw_chain, &deny);
-
- printf("IP firewall initialized, ");
+
+ printf("IP packet filtering initialized, "
+#ifdef IPDIVERT
+ "divert enabled, ");
+#else
+ "divert disabled, ");
+#endif
#ifndef IPFIREWALL_VERBOSE
printf("logging disabled\n");
#else
if (fw_verbose_limit == 0)
printf("unlimited logging\n");
else
- printf("logging limited to %d packets/entry\n", fw_verbose_limit);
+ printf("logging limited to %d packets/entry\n",
+ fw_verbose_limit);
#endif
}
OpenPOWER on IntegriCloud