freeBSD /ipfw/ divert socket
Kelly Yancey
kbyanc at posi.net
Tue Apr 25 02:57:16 UTC 2006
On Fri, 21 Apr 2006, Amit Mondal wrote:
> Hi All,
>
> I need a little help with FreeBSD Kernel stuff. I wanna use Divert Socket to
> sniff IP packet in FreeBSD.
> For that I have compiled the kernel with options IPDIVERT and everything is
> ok.
>
> Now, when I am not really sniffing and re-injecting the packet back to the
> network stack, it is basically dropping all the packets. But I want it
> pass-through it, when no application is reading at divert socket. My
> question is, HOW CAN I MAKE IT PASS-THROUGH? IF NO APPLICATION IS READING
> FROM DIVERT SOCKET, IT SHOULD WORK AS IF THERE IS NO DIVERT SOCKET.
>
> Thanks in adavnce
>
> Rgds
> Amit
>
Attached is a really old patch I made against FreeBSD 4.7. It might
apply to 4.9. Even if it doesn't, it should give you a pretty good idea
how to implement the functionality you desire.
Kelly
--
Kelly Yancey - kbyanc@{posi.net,FreeBSD.org} - kelly at nttmcl.com
FreeBSD, The Power To Serve: http://www.freebsd.org/
-------------- next part --------------
Index: ip_fw2.c
===================================================================
RCS file: /home/cvs/acs/base/src/sys/netinet/ip_fw2.c,v
retrieving revision 1.9
retrieving revision 1.11
diff -u -p -r1.9 -r1.11
--- ip_fw2.c 3 Jan 2003 23:34:19 -0000 1.9
+++ ip_fw2.c 8 Jan 2003 06:14:48 -0000 1.11
@@ -580,17 +580,17 @@ ipfw_log(struct ip_fw *f, u_int hlen, st
}
if (oif || m->m_pkthdr.rcvif)
log(LOG_SECURITY | LOG_INFO,
- "ipfw: %d %s %s %s via %s%d%s\n",
+ "ipfw: %d %s %s %s via %s%d%s (layer %d)\n",
f ? f->rulenum : -1,
action, proto, oif ? "out" : "in",
oif ? oif->if_name : m->m_pkthdr.rcvif->if_name,
oif ? oif->if_unit : m->m_pkthdr.rcvif->if_unit,
- fragment);
+ fragment, eh ? 2 : 3);
else
log(LOG_SECURITY | LOG_INFO,
- "ipfw: %d %s %s [no if info]%s\n",
+ "ipfw: %d %s %s [no if info]%s (layer %d)\n",
f ? f->rulenum : -1,
- action, proto, fragment);
+ action, proto, fragment, eh ? 2 : 3);
if (limit_reached)
log(LOG_SECURITY | LOG_NOTICE,
"ipfw: limit %d reached on entry %d\n",
@@ -1939,8 +1939,10 @@ check_body:
goto done;
case O_FORWARD_IP:
- if (args->eh) /* not valid on layer2 pkts */
- break;
+ if (args->eh && oif != NULL) {
+ /* ignore outbound layer2 pkts */
+ goto next_rule;
+ }
if (!q || dyn_dir == MATCH_FORWARD)
args->next_hop =
&((ipfw_insn_sa *)cmd)->sa;
Index: ip_input.c
===================================================================
RCS file: /home/cvs/acs/base/src/sys/netinet/ip_input.c,v
retrieving revision 1.14
retrieving revision 1.16
diff -u -p -r1.14 -r1.16
--- ip_input.c 3 Jan 2003 04:46:53 -0000 1.14
+++ ip_input.c 8 Jan 2003 06:16:06 -0000 1.16
@@ -369,8 +369,18 @@ ip_input(struct mbuf *m)
case PACKET_TAG_IPFORWARD:
args.next_hop = (struct sockaddr_in *)m->m_hdr.mh_data;
break;
+ case PACKET_TAG_IPFORWARD | M_PROTO5: {
+ /* XXX This should be taken out and shot! */
+ struct mbuf *tag = m;
+ m = m->m_next;
+ args.next_hop = (struct sockaddr_in *)tag->m_hdr.mh_data;
+ m_free(tag);
+ KASSERT(m->m_type != MT_TAG, ("XXX kill me"));
+ goto posttags;
+ }
}
}
+posttags:
KASSERT(m != NULL && (m->m_flags & M_PKTHDR) != 0,
("ip_input: no HDR"));
Index: if_ethersubr.c
===================================================================
RCS file: /home/cvs/acs/base/src/sys/net/if_ethersubr.c,v
retrieving revision 1.9
retrieving revision 1.11
diff -u -p -r1.9 -r1.11
--- if_ethersubr.c 3 Jan 2003 04:40:06 -0000 1.9
+++ if_ethersubr.c 8 Jan 2003 06:16:05 -0000 1.11
@@ -501,7 +501,7 @@ ether_ipfw_chk(struct mbuf **m0, struct
args.oif = flags & ETHER_IPFW_OUTPUT ? ifp : NULL;
args.divert_rule = divert_rule;
args.rule = *rule; /* matching rule to restart */
- args.next_hop = NULL; /* we do not support forward yet */
+ args.next_hop = NULL; /* IPFORWARD */
args.eh = &save_eh; /* MAC header for bridged/MAC packets */
i = ip_fw_chk_ptr(&args);
*m0 = args.m;
@@ -510,7 +510,7 @@ ether_ipfw_chk(struct mbuf **m0, struct
if ( (i & IP_FW_PORT_DENY_FLAG) || *m0 == NULL) /* drop */
return 0;
- if (i == 0) /* a PASS rule. */
+ if (i == 0 && args.next_hop == NULL) /* a PASS rule. */
return 1;
if (DUMMYNET_LOADED && (i & IP_FW_PORT_DYNT_FLAG)) {
@@ -589,6 +589,36 @@ ether_ipfw_chk(struct mbuf **m0, struct
/* If 'tee', continue with original packet */
return (clone != NULL);
+ }
+#endif
+
+#ifdef INET
+ /*
+ * IPFIREWALL_FORWARD
+ *
+ * XXX Only support IP forwarding during in-bound processing.
+ */
+ if (i == 0 && args.next_hop != NULL && args.oif == NULL) {
+ /*
+ * Packet must be IP to match an IP forward rule. Tag it and
+ * pass it along to ip_input() for processing.
+ * XXX Relies on nothing in the netisr processing examining
+ * the leading mbuf as it's our tag rather than a proper
+ * packet header.
+ * XXX This is pretty expensive (and ugly!). This can be
+ * cleaned up using -current's packet tagging.
+ */
+ struct mbuf *tag;
+
+ MGETHDR(tag, M_DONTWAIT, MT_TAG);
+ tag->m_hdr.mh_flags = PACKET_TAG_IPFORWARD | M_PROTO5; /* Hack! */
+ tag->m_hdr.mh_data = (caddr_t)args.next_hop;
+ tag->m_hdr.mh_next = *m0;
+
+ schednetisr(NETISR_IP);
+ (void) IF_HANDOFF(&ipintrq, tag, NULL);
+ *m0 = NULL;
+ return 0;
}
#endif
More information about the freebsd-net
mailing list