summaryrefslogtreecommitdiffstats
path: root/sys/netinet/ip_divert.c
diff options
context:
space:
mode:
authorluigi <luigi@FreeBSD.org>2010-01-04 19:01:22 +0000
committerluigi <luigi@FreeBSD.org>2010-01-04 19:01:22 +0000
commit40024ff7c3bf948cb45283aec877bd552ee934d7 (patch)
treee632a2ed87ca91743db2bb3ace9525de5d414d89 /sys/netinet/ip_divert.c
parentd2744b88e92689da349b5de750666f235ea9a4ce (diff)
downloadFreeBSD-src-40024ff7c3bf948cb45283aec877bd552ee934d7.zip
FreeBSD-src-40024ff7c3bf948cb45283aec877bd552ee934d7.tar.gz
Various cleanup done in ipfw3-head branch including:
- use a uniform mtag format for all packets that exit and re-enter the firewall in the middle of a rulechain. On reentry, all tags containing reinject info are renamed to MTAG_IPFW_RULE so the processing is simpler. - make ipfw and dummynet use ip_len and ip_off in network format everywhere. Conversion is done only once instead of tracking the format in every place. - use a macro FREE_PKT to dispose of mbufs. This eases portability. On passing i also removed a few typos, staticise or localise variables, remove useless declarations and other minor things. Overall the code shrinks a bit and is hopefully more readable. I have tested functionality for all but ng_ipfw and if_bridge/if_ethersubr. For ng_ipfw i am actually waiting for feedback from glebius@ because we might have some small changes to make. For if_bridge and if_ethersubr feedback would be welcome (there are still some redundant parts in these two modules that I would like to remove, but first i need to check functionality).
Diffstat (limited to 'sys/netinet/ip_divert.c')
-rw-r--r--sys/netinet/ip_divert.c56
1 files changed, 28 insertions, 28 deletions
diff --git a/sys/netinet/ip_divert.c b/sys/netinet/ip_divert.c
index 85c619f..811ca06 100644
--- a/sys/netinet/ip_divert.c
+++ b/sys/netinet/ip_divert.c
@@ -52,19 +52,12 @@ __FBSDID("$FreeBSD$");
#include <sys/priv.h>
#include <sys/proc.h>
#include <sys/protosw.h>
-#include <sys/rwlock.h>
-#include <sys/signalvar.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
-#include <sys/sx.h>
#include <sys/sysctl.h>
-#include <sys/systm.h>
-
-#include <vm/uma.h>
#include <net/if.h>
#include <net/netisr.h>
-#include <net/route.h>
#include <net/vnet.h>
#include <netinet/in.h>
@@ -72,7 +65,6 @@ __FBSDID("$FreeBSD$");
#include <netinet/in_systm.h>
#include <netinet/in_var.h>
#include <netinet/ip.h>
-#include <netinet/ip_divert.h>
#include <netinet/ip_var.h>
#include <netinet/ip_fw.h>
#include <netinet/ipfw/ip_fw_private.h>
@@ -194,7 +186,7 @@ div_destroy(void)
* IPPROTO_DIVERT is not in the real IP protocol number space; this
* function should never be called. Just in case, drop any packets.
*/
-void
+static void
div_input(struct mbuf *m, int off)
{
@@ -218,9 +210,8 @@ divert_packet(struct mbuf *m, int incoming)
struct sockaddr_in divsrc;
struct m_tag *mtag;
- mtag = m_tag_find(m, PACKET_TAG_DIVERT, NULL);
+ mtag = m_tag_locate(m, MTAG_IPFW_RULE, 0, NULL);
if (mtag == NULL) {
- printf("%s: no divert tag\n", __func__);
m_freem(m);
return;
}
@@ -245,14 +236,15 @@ divert_packet(struct mbuf *m, int incoming)
ip->ip_len = htons(ip->ip_len);
}
#endif
+ bzero(&divsrc, sizeof(divsrc));
+ divsrc.sin_len = sizeof(divsrc);
+ divsrc.sin_family = AF_INET;
+ /* record matching rule, in host format */
+ divsrc.sin_port = ((struct ipfw_rule_ref *)(mtag+1))->rulenum;
/*
* Record receive interface address, if any.
* But only for incoming packets.
*/
- bzero(&divsrc, sizeof(divsrc));
- divsrc.sin_len = sizeof(divsrc);
- divsrc.sin_family = AF_INET;
- divsrc.sin_port = divert_cookie(mtag); /* record matching rule */
if (incoming) {
struct ifaddr *ifa;
struct ifnet *ifp;
@@ -300,7 +292,7 @@ divert_packet(struct mbuf *m, int incoming)
/* Put packet on socket queue, if any */
sa = NULL;
- nport = htons((u_int16_t)divert_info(mtag));
+ nport = htons((u_int16_t)(((struct ipfw_rule_ref *)(mtag+1))->info));
INP_INFO_RLOCK(&V_divcbinfo);
LIST_FOREACH(inp, &V_divcb, inp_list) {
/* XXX why does only one socket match? */
@@ -339,7 +331,7 @@ div_output(struct socket *so, struct mbuf *m, struct sockaddr_in *sin,
struct mbuf *control)
{
struct m_tag *mtag;
- struct divert_tag *dt;
+ struct ipfw_rule_ref *dt;
int error = 0;
struct mbuf *options;
@@ -354,23 +346,31 @@ div_output(struct socket *so, struct mbuf *m, struct sockaddr_in *sin,
if (control)
m_freem(control); /* XXX */
- if ((mtag = m_tag_find(m, PACKET_TAG_DIVERT, NULL)) == NULL) {
- mtag = m_tag_get(PACKET_TAG_DIVERT, sizeof(struct divert_tag),
- M_NOWAIT | M_ZERO);
+ mtag = m_tag_locate(m, MTAG_IPFW_RULE, 0, NULL);
+ if (mtag == NULL) {
+ /* this should be normal */
+ mtag = m_tag_alloc(MTAG_IPFW_RULE, 0,
+ sizeof(struct ipfw_rule_ref), M_NOWAIT | M_ZERO);
if (mtag == NULL) {
error = ENOBUFS;
goto cantsend;
}
- dt = (struct divert_tag *)(mtag+1);
m_tag_prepend(m, mtag);
- } else
- dt = (struct divert_tag *)(mtag+1);
+ }
+ dt = (struct ipfw_rule_ref *)(mtag+1);
/* Loopback avoidance and state recovery */
if (sin) {
int i;
- dt->cookie = sin->sin_port;
+ /* set the starting point. We provide a non-zero slot,
+ * but a non_matching chain_id to skip that info and use
+ * the rulenum/rule_id.
+ */
+ dt->slot = 1; /* dummy, chain_id is invalid */
+ dt->chain_id = 0;
+ dt->rulenum = sin->sin_port+1; /* host format ? */
+ dt->rule_id = 0;
/*
* Find receive interface with the given name, stuffed
* (if it exists) in the sin_zero[] field.
@@ -388,7 +388,7 @@ div_output(struct socket *so, struct mbuf *m, struct sockaddr_in *sin,
struct ip *const ip = mtod(m, struct ip *);
struct inpcb *inp;
- dt->info |= IP_FW_DIVERT_OUTPUT_FLAG;
+ dt->info |= IPFW_IS_DIVERT | IPFW_INFO_OUT;
INP_INFO_WLOCK(&V_divcbinfo);
inp = sotoinpcb(so);
INP_RLOCK(inp);
@@ -454,7 +454,7 @@ div_output(struct socket *so, struct mbuf *m, struct sockaddr_in *sin,
m_freem(options);
}
} else {
- dt->info |= IP_FW_DIVERT_LOOPBACK_FLAG;
+ dt->info |= IPFW_IS_DIVERT | IPFW_INFO_IN;
if (m->m_pkthdr.rcvif == NULL) {
/*
* No luck with the name, check by IP address.
@@ -588,7 +588,7 @@ div_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
return div_output(so, m, (struct sockaddr_in *)nam, control);
}
-void
+static void
div_ctlinput(int cmd, struct sockaddr *sa, void *vip)
{
struct in_addr faddr;
@@ -801,5 +801,5 @@ static moduledata_t ipdivertmod = {
};
DECLARE_MODULE(ipdivert, ipdivertmod, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY);
-MODULE_DEPEND(dummynet, ipfw, 2, 2, 2);
+MODULE_DEPEND(ipdivert, ipfw, 2, 2, 2);
MODULE_VERSION(ipdivert, 1);
OpenPOWER on IntegriCloud