summaryrefslogtreecommitdiffstats
path: root/sys/netinet
diff options
context:
space:
mode:
authorluigi <luigi@FreeBSD.org>2002-05-09 10:34:57 +0000
committerluigi <luigi@FreeBSD.org>2002-05-09 10:34:57 +0000
commit23cf222c8133558823b20c5e939ce537d5099c9e (patch)
tree290f0a0b2936ec4f8d0958565aefddebe98c19a9 /sys/netinet
parentb6d1cd6b33e9d941abd387b6b03841797624e220 (diff)
downloadFreeBSD-src-23cf222c8133558823b20c5e939ce537d5099c9e.zip
FreeBSD-src-23cf222c8133558823b20c5e939ce537d5099c9e.tar.gz
Cleanup the interface to ip_fw_chk, two of the input arguments
were totally useless and have been removed. ip_input.c, ip_output.c: Properly initialize the "ip" pointer in case the firewall does an m_pullup() on the packet. Remove some debugging code forgotten long ago. ip_fw.[ch], bridge.c: Prepare the grounds for matching MAC header fields in bridged packets, so we can have 'etherfw' functionality without a lot of kernel and userland bloat.
Diffstat (limited to 'sys/netinet')
-rw-r--r--sys/netinet/ip_fw.c157
-rw-r--r--sys/netinet/ip_fw.h22
-rw-r--r--sys/netinet/ip_input.c16
-rw-r--r--sys/netinet/ip_output.c17
4 files changed, 108 insertions, 104 deletions
diff --git a/sys/netinet/ip_fw.c b/sys/netinet/ip_fw.c
index e552e1d..b06576a 100644
--- a/sys/netinet/ip_fw.c
+++ b/sys/netinet/ip_fw.c
@@ -222,16 +222,13 @@ static __inline int
int range_flag, int mask);
static int tcpflg_match (struct tcphdr *tcp, struct ip_fw *f);
static int icmptype_match (struct icmp * icmp, struct ip_fw * f);
-static void ipfw_report (struct ip_fw *f, struct ip *ip, int offset,
+static void ipfw_report (struct ip_fw *f, struct ip *ip, int ip_off,
int ip_len, struct ifnet *rif,
struct ifnet *oif);
static void flush_rule_ptrs(void);
-static int ip_fw_chk (struct ip **pip, int hlen,
- struct ifnet *oif, u_int16_t *cookie, struct mbuf **m,
- struct ip_fw **flow_id,
- struct sockaddr_in **next_hop);
+static ip_fw_chk_t ip_fw_chk;
static int ip_fw_ctl (struct sockopt *sopt);
ip_dn_ruledel_t *ip_dn_ruledel_ptr = NULL;
@@ -509,7 +506,7 @@ iface_match(struct ifnet *ifp, union ip_fw_if *ifu, int byname)
}
static void
-ipfw_report(struct ip_fw *f, struct ip *ip, int offset, int ip_len,
+ipfw_report(struct ip_fw *f, struct ip *ip, int ip_off, int ip_len,
struct ifnet *rif, struct ifnet *oif)
{
struct tcphdr *const tcp = (struct tcphdr *) ((u_int32_t *) ip+ ip->ip_hl);
@@ -519,6 +516,7 @@ ipfw_report(struct ip_fw *f, struct ip *ip, int offset, int ip_len,
char *action;
char action2[32], proto[47], name[18], fragment[27];
int len;
+ int offset = ip_off & IP_OFFMASK;
count = f ? f->fw_pcnt : ++counter;
if ((f == NULL && fw_verbose_limit != 0 && count > fw_verbose_limit) ||
@@ -634,11 +632,11 @@ ipfw_report(struct ip_fw *f, struct ip *ip, int offset, int ip_len,
break;
}
- if (ip->ip_off & (IP_MF | IP_OFFMASK))
+ if (ip_off & (IP_MF | IP_OFFMASK))
snprintf(SNPARGS(fragment, 0), " (frag %d:%d@%d%s)",
ntohs(ip->ip_id), ip_len - (ip->ip_hl << 2),
offset << 3,
- (ip->ip_off & IP_MF) ? "+" : "");
+ (ip_off & IP_MF) ? "+" : "");
else
fragment[0] = '\0';
if (oif)
@@ -1061,15 +1059,14 @@ lookup_next_rule(struct ip_fw *me)
/*
* Parameters:
*
- * pip Pointer to packet header (struct ip **)
- * hlen Packet header length
+ * *m The packet; we set to NULL when/if we nuke it.
* oif Outgoing interface, or NULL if packet is incoming
* *cookie Skip up to the first rule past this rule number;
* upon return, non-zero port number for divert or tee.
* Special case: cookie == NULL on input for bridging.
- * *m The packet; we set to NULL when/if we nuke it.
* *flow_id pointer to the last matching rule (in/out)
* *next_hop socket we are forwarding to (in/out).
+ * For bridged packets, this is a pointer to the MAC header.
*
* Return value:
*
@@ -1087,32 +1084,38 @@ lookup_next_rule(struct ip_fw *me)
*/
static int
-ip_fw_chk(struct ip **pip, int hlen,
- struct ifnet *oif, u_int16_t *cookie, struct mbuf **m,
- struct ip_fw **flow_id,
- struct sockaddr_in **next_hop)
+ip_fw_chk(struct mbuf **m, struct ifnet *oif, u_int16_t *cookie,
+ struct ip_fw **flow_id, struct sockaddr_in **next_hop)
{
struct ip_fw *f = NULL; /* matching rule */
- struct ip *ip = *pip;
+ struct ip *ip = mtod(*m, struct ip *);
struct ifnet *const rif = (*m)->m_pkthdr.rcvif;
struct ifnet *tif;
+ u_int hlen = ip->ip_hl << 2;
+ struct ether_header * eh = NULL;
- u_short offset = 0 ;
+ u_short ip_off=0, offset = 0 ;
+ /* local copy of addresses for faster matching */
u_short src_port = 0, dst_port = 0;
- struct in_addr src_ip, dst_ip; /* XXX */
- u_int8_t proto= 0, flags = 0 ; /* XXX */
+ struct in_addr src_ip, dst_ip;
+ u_int8_t proto= 0, flags = 0;
+
u_int16_t skipto, bridgeCookie;
- u_int16_t ip_len;
+ u_int16_t ip_len=0;
int dyn_checked = 0 ; /* set after dyn.rules have been checked. */
int direction = MATCH_FORWARD ; /* dirty trick... */
struct ipfw_dyn_rule *q = NULL ;
- /* Special hack for bridging (as usual) */
- if (cookie == NULL) {
+#define BRIDGED (cookie == &bridgeCookie)
+ if (cookie == NULL) { /* this is a bridged packet */
bridgeCookie = 0;
cookie = &bridgeCookie;
-#define BRIDGED (cookie == &bridgeCookie)
+ eh = (struct ether_header *)next_hop;
+ if ( (*m)->m_pkthdr.len >= sizeof(struct ip) &&
+ ntohs(eh->ether_type) == ETHERTYPE_IP)
+ hlen = ip->ip_hl << 2;
+ } else {
hlen = ip->ip_hl << 2;
}
@@ -1120,63 +1123,67 @@ ip_fw_chk(struct ip **pip, int hlen,
skipto = *cookie;
*cookie = 0;
-#define PULLUP_TO(len) do { \
- if ((*m)->m_len < (len)) { \
- ip = NULL ; \
- if ((*m = m_pullup(*m, (len))) == 0) \
- goto bogusfrag; \
- ip = mtod(*m, struct ip *); \
- *pip = ip; \
- } \
- } while (0)
-
/*
* Collect parameters into local variables for faster matching.
*/
- proto = ip->ip_p;
- src_ip = ip->ip_src;
- dst_ip = ip->ip_dst;
- if (0 && BRIDGED) { /* not yet... */
- offset = (ntohs(ip->ip_off) & IP_OFFMASK);
- ip_len = ntohs(ip->ip_len);
- } else {
- offset = (ip->ip_off & IP_OFFMASK);
- ip_len = ip->ip_len;
- }
- if (offset == 0) {
- switch (proto) {
- case IPPROTO_TCP : {
- struct tcphdr *tcp;
-
- PULLUP_TO(hlen + sizeof(struct tcphdr));
- tcp =(struct tcphdr *)((u_int32_t *)ip + ip->ip_hl);
- dst_port = tcp->th_dport ;
- src_port = tcp->th_sport ;
- flags = tcp->th_flags ;
- }
- break ;
+ if (hlen > 0) { /* this is an IP packet */
+ proto = ip->ip_p;
+ src_ip = ip->ip_src;
+ dst_ip = ip->ip_dst;
+ if (BRIDGED) { /* not yet... */
+ ip_off = ntohs(ip->ip_off);
+ ip_len = ntohs(ip->ip_len);
+ } else {
+ ip_off = ip->ip_off;
+ ip_len = ip->ip_len;
+ }
+ offset = ip_off & IP_OFFMASK;
+ if (offset == 0) {
+
+#define PULLUP_TO(len) \
+ do { \
+ if ((*m)->m_len < (len)) { \
+ *m = m_pullup(*m, (len)); \
+ if (*m == 0) \
+ goto bogusfrag; \
+ ip = mtod(*m, struct ip *); \
+ } \
+ } while (0)
- case IPPROTO_UDP : {
- struct udphdr *udp;
+ switch (proto) {
+ case IPPROTO_TCP : {
+ struct tcphdr *tcp;
+
+ PULLUP_TO(hlen + sizeof(struct tcphdr));
+ tcp =(struct tcphdr *)((u_int32_t *)ip + ip->ip_hl);
+ dst_port = tcp->th_dport ;
+ src_port = tcp->th_sport ;
+ flags = tcp->th_flags ;
+ }
+ break ;
- PULLUP_TO(hlen + sizeof(struct udphdr));
- udp =(struct udphdr *)((u_int32_t *)ip + ip->ip_hl);
- dst_port = udp->uh_dport ;
- src_port = udp->uh_sport ;
- }
- break;
+ case IPPROTO_UDP : {
+ struct udphdr *udp;
- case IPPROTO_ICMP:
- PULLUP_TO(hlen + 4); /* type, code and checksum. */
- flags = ((struct icmp *)
- ((u_int32_t *)ip + ip->ip_hl))->icmp_type ;
- break ;
+ PULLUP_TO(hlen + sizeof(struct udphdr));
+ udp =(struct udphdr *)((u_int32_t *)ip + ip->ip_hl);
+ dst_port = udp->uh_dport ;
+ src_port = udp->uh_sport ;
+ }
+ break;
- default :
- break;
+ case IPPROTO_ICMP:
+ PULLUP_TO(hlen + 4); /* type, code and checksum. */
+ flags = ((struct icmp *)
+ ((u_int32_t *)ip + ip->ip_hl))->icmp_type ;
+ break ;
+
+ default :
+ break;
+ }
+#undef PULLUP_TO
}
}
-#undef PULLUP_TO
last_pkt.src_ip = ntohl(src_ip.s_addr);
last_pkt.dst_ip = ntohl(dst_ip.s_addr);
last_pkt.proto = proto;
@@ -1471,8 +1478,8 @@ check_ports:
bogusfrag:
if (fw_verbose) {
- if (ip != NULL)
- ipfw_report(NULL, ip, offset, ip_len, rif, oif);
+ if (*m != NULL)
+ ipfw_report(NULL, ip, ip_off, ip_len, rif, oif);
else
printf("pullup failed\n");
}
@@ -1498,8 +1505,8 @@ got_match:
f->timestamp = time_second;
/* Log to console if desired */
- if ((f->fw_flg & IP_FW_F_PRN) && fw_verbose)
- ipfw_report(f, ip, offset, ip_len, rif, oif);
+ if ((f->fw_flg & IP_FW_F_PRN) && fw_verbose && hlen >0)
+ ipfw_report(f, ip, ip_off, ip_len, rif, oif);
/* Take appropriate action */
switch (f->fw_flg & IP_FW_F_COMMAND) {
diff --git a/sys/netinet/ip_fw.h b/sys/netinet/ip_fw.h
index 468d66f..c41eb31 100644
--- a/sys/netinet/ip_fw.h
+++ b/sys/netinet/ip_fw.h
@@ -49,11 +49,26 @@ union ip_fw_if {
* Port numbers are stored in HOST byte order.
*/
+/*
+ * To match MAC headers:
+ * 12 bytes at fw_mac_hdr contain the dst-src MAC address after masking.
+ * 12 bytes at fw_mac_mask contain the mask to apply to dst-src
+ * 2 bytes at fw_mac_type contain the mac type after mask (in net format)
+ * 2 bytes at fw_mac_type_mask contain the mac type mask
+ * If IP_FW_F_SRNG, the two contain the low-high of a range of types.
+ * IP_FW_F_DRNG is used to indicare we want to match a vlan.
+ */
+#define fw_mac_hdr fw_src
+#define fw_mac_mask fw_uar
+#define fw_mac_type fw_iplen
+#define fw_mac_mask_type fw_ipid
+
struct ip_fw {
LIST_ENTRY(ip_fw) next; /* bidirectional list of rules */
u_int fw_flg; /* Operational Flags word */
u_int64_t fw_pcnt; /* Packet counters */
u_int64_t fw_bcnt; /* Byte counters */
+
struct in_addr fw_src; /* Source IP address */
struct in_addr fw_dst; /* Destination IP address */
struct in_addr fw_smsk; /* Mask for source IP address */
@@ -238,8 +253,9 @@ struct ipfw_dyn_rule {
#define IP_FW_F_CHECK_S 0x10000000 /* check state */
#define IP_FW_F_SME 0x20000000 /* source = me */
#define IP_FW_F_DME 0x40000000 /* destination = me */
+#define IP_FW_F_MAC 0x80000000 /* match MAC header */
-#define IP_FW_F_MASK 0x7FFFFFFF /* All possible flag bits mask */
+#define IP_FW_F_MASK 0xFFFFFFFF /* All possible flag bits mask */
/*
* Flags for the 'fw_ipflg' field, for comparing values
@@ -320,8 +336,8 @@ void ip_fw_init(void);
/* Firewall hooks */
struct ip;
struct sockopt;
-typedef int ip_fw_chk_t (struct ip **, int, struct ifnet *, u_int16_t *,
- struct mbuf **, struct ip_fw **, struct sockaddr_in **);
+typedef int ip_fw_chk_t (struct mbuf **m, struct ifnet *oif,
+ u_int16_t *cookie, struct ip_fw **rule, struct sockaddr_in **next_hop);
typedef int ip_fw_ctl_t (struct sockopt *);
extern ip_fw_chk_t *ip_fw_chk_ptr;
extern ip_fw_ctl_t *ip_fw_ctl_ptr;
diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c
index b720bdd..79d5123 100644
--- a/sys/netinet/ip_input.c
+++ b/sys/netinet/ip_input.c
@@ -450,22 +450,14 @@ iphack:
* See the comment in ip_output for the return values
* produced by the firewall.
*/
- i = ip_fw_chk_ptr(&ip, hlen, NULL,
- &divert_cookie, &m, &rule, &ip_fw_fwd_addr);
- if (i & IP_FW_PORT_DENY_FLAG) { /* XXX new interface-denied */
+ i = ip_fw_chk_ptr(&m, NULL /* oif */, &divert_cookie,
+ &rule, &ip_fw_fwd_addr);
+ if ( (i & IP_FW_PORT_DENY_FLAG) || m == NULL) { /* drop */
if (m)
m_freem(m);
return;
}
- if (m == NULL) { /* Packet discarded by firewall */
- static int __debug=10;
- if (__debug > 0) {
- printf(
- "firewall returns NULL, please update!\n");
- __debug--;
- }
- return;
- }
+ ip = mtod(m, struct ip *); /* just in case m changed */
if (i == 0 && ip_fw_fwd_addr == NULL) /* common case */
goto pass;
if (DUMMYNET_LOADED && (i & IP_FW_PORT_DYNT_FLAG) != 0) {
diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c
index d3628f1..d9d2145 100644
--- a/sys/netinet/ip_output.c
+++ b/sys/netinet/ip_output.c
@@ -610,8 +610,7 @@ skip_ipsec:
if (fw_enable && IPFW_LOADED && !ip_fw_fwd_addr) {
struct sockaddr_in *old = dst;
- off = ip_fw_chk_ptr(&ip,
- hlen, ifp, &divert_cookie, &m, &rule, &dst);
+ off = ip_fw_chk_ptr(&m, ifp, &divert_cookie, &rule, &dst);
/*
* On return we must do the following:
* m == NULL -> drop the pkt (old interface, deprecated)
@@ -627,23 +626,13 @@ skip_ipsec:
* unsupported rules), but better play safe and drop
* packets in case of doubt.
*/
- if (off & IP_FW_PORT_DENY_FLAG) { /* XXX new interface-denied */
+ if ( (off & IP_FW_PORT_DENY_FLAG) || m == NULL) {
if (m)
m_freem(m);
error = EACCES;
goto done;
}
- if (!m) { /* firewall said to reject */
- static int __debug=10;
-
- if (__debug > 0) {
- printf(
- "firewall returns NULL, please update!\n");
- __debug--;
- }
- error = EACCES;
- goto done;
- }
+ ip = mtod(m, struct ip *);
if (off == 0 && dst == old) /* common case */
goto pass;
if (DUMMYNET_LOADED && (off & IP_FW_PORT_DYNT_FLAG) != 0) {
OpenPOWER on IntegriCloud