summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorNiels Provos <provos@cvs.openbsd.org>2001-06-25 20:48:18 +0000
committerNiels Provos <provos@cvs.openbsd.org>2001-06-25 20:48:18 +0000
commitd7aea208023a136429b6e7996563c4a0886f4620 (patch)
treeb49bb4ac7452af270cc3f83dfcaabafedd98ed34 /sys
parentff92ff78ad1439a28f881d242014ee4b153e4bd3 (diff)
first stab at packet logging for pf. inspired by late night dreams of art.
we just pass drop and passed packets to different pseudo interface that can be listened to with bpf.
Diffstat (limited to 'sys')
-rw-r--r--sys/conf/GENERIC3
-rw-r--r--sys/conf/files4
-rw-r--r--sys/net/if_pflog.c198
-rw-r--r--sys/net/if_pflog.h50
-rw-r--r--sys/net/pf.c127
5 files changed, 322 insertions, 60 deletions
diff --git a/sys/conf/GENERIC b/sys/conf/GENERIC
index 9eb38726c42..a09a0a8755f 100644
--- a/sys/conf/GENERIC
+++ b/sys/conf/GENERIC
@@ -1,4 +1,4 @@
-# $OpenBSD: GENERIC,v 1.77 2001/06/25 04:31:50 kjell Exp $
+# $OpenBSD: GENERIC,v 1.78 2001/06/25 20:48:13 provos Exp $
#
# Machine-independent option; used by all architectures for their
# GENERIC kernel
@@ -80,6 +80,7 @@ option PPP_DEFLATE
#option MROUTING # Multicast router
pseudo-device pf 1 # packet filter
+pseudo-device pflog 2 # pf log if
pseudo-device loop 2 # network loopback
pseudo-device bpfilter 8 # packet filter
pseudo-device sl 2 # CSLIP
diff --git a/sys/conf/files b/sys/conf/files
index 0af2a2d4dc3..1e867f54d35 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -1,4 +1,4 @@
-# $OpenBSD: files,v 1.207 2001/06/25 03:28:01 csapuntz Exp $
+# $OpenBSD: files,v 1.208 2001/06/25 20:48:15 provos Exp $
# $NetBSD: files,v 1.87 1996/05/19 17:17:50 jonathan Exp $
# @(#)files.newconf 7.5 (Berkeley) 5/10/93
@@ -278,6 +278,7 @@ pseudo-device tun: ifnet
pseudo-device bpfilter: ifnet
pseudo-device strip: ifnet
pseudo-device enc: ifnet
+pseudo-device pflog: ifnet
pseudo-device bridge: ifnet, ether
pseudo-device vlan: ifnet, ether
pseudo-device sppp: ifnet
@@ -563,6 +564,7 @@ file net/route.c
file net/rtsock.c
file net/slcompress.c sl | ppp | strip
file net/if_enc.c enc needs-count
+file net/if_pflog.c pflog needs-count
file net/if_gre.c gre needs-count
file netccitt/ccitt_proto.c ccitt
file netccitt/hd_debug.c hdlc
diff --git a/sys/net/if_pflog.c b/sys/net/if_pflog.c
new file mode 100644
index 00000000000..403b56b7dab
--- /dev/null
+++ b/sys/net/if_pflog.c
@@ -0,0 +1,198 @@
+/* $OpenBSD: if_pflog.c,v 1.1 2001/06/25 20:48:16 provos Exp $ */
+/*
+ * The authors of this code are John Ioannidis (ji@tla.org),
+ * Angelos D. Keromytis (kermit@csd.uch.gr) and
+ * Niels Provos (provos@physnet.uni-hamburg.de).
+ *
+ * This code was written by John Ioannidis for BSD/OS in Athens, Greece,
+ * in November 1995.
+ *
+ * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996,
+ * by Angelos D. Keromytis.
+ *
+ * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis
+ * and Niels Provos.
+ *
+ * Copyright (C) 1995, 1996, 1997, 1998 by John Ioannidis, Angelos D. Keromytis
+ * and Niels Provos.
+ * Copyright (c) 2001, Angelos D. Keromytis.
+ *
+ * Permission to use, copy, and modify this software with or without fee
+ * is hereby granted, provided that this entire notice is included in
+ * all copies of any software which is or includes a copy or
+ * modification of this software.
+ * You may use this code under the GNU public license if you so wish. Please
+ * contribute changes back to the authors under this freer than GPL license
+ * so that we may further the use of strong encryption without limitations to
+ * all.
+ *
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
+ * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
+ * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
+ * PURPOSE.
+ */
+
+/*
+ * Encapsulation interface driver.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+
+#include <net/if.h>
+#include <net/if_types.h>
+#include <net/route.h>
+#include <net/bpf.h>
+
+#include <net/if_pflog.h>
+
+#ifdef INET
+#include <netinet/in.h>
+#include <netinet/in_var.h>
+#endif
+
+#ifdef INET6
+#ifndef INET
+#include <netinet/in.h>
+#endif
+#include <netinet6/nd6.h>
+#endif /* INET6 */
+
+#ifdef ISO
+extern struct ifqueue clnlintrq;
+#endif
+
+#ifdef NS
+extern struct ifqueue nsintrq;
+#endif
+
+#include "bpfilter.h"
+#include "pflog.h"
+
+#define PFLOGMTU (32768 + MHLEN + MLEN)
+
+#ifdef PFLOGDEBUG
+#define DPRINTF(x) do { if (pflogdebug) printf x ; } while (0)
+#else
+#define DPRINTF(x)
+#endif
+
+#if NPFLOG != 2
+#error "if_plog needs exactly two interfaces, fix sys/conf/GENERIC"
+#endif
+
+struct pflog_softc pflogif[NPFLOG];
+
+void pflogattach __P((int));
+int pflogoutput __P((struct ifnet *, struct mbuf *, struct sockaddr *,
+ struct rtentry *));
+int pflogioctl __P((struct ifnet *, u_long, caddr_t));
+void pflogrtrequest __P((int, struct rtentry *, struct sockaddr *));
+void pflogstart __P((struct ifnet *));
+
+extern int ifqmaxlen;
+
+void
+pflogattach(int npflog)
+{
+ struct ifnet *ifp;
+ int i;
+
+ bzero(pflogif, sizeof(pflogif));
+
+ for (i = 0; i < NPFLOG; i++) {
+ ifp = &pflogif[i].sc_if;
+ sprintf(ifp->if_xname, "pflog%d", i);
+ ifp->if_softc = &pflogif[i];
+ ifp->if_mtu = PFLOGMTU;
+ ifp->if_ioctl = pflogioctl;
+ ifp->if_output = pflogoutput;
+ ifp->if_start = pflogstart;
+ ifp->if_type = IFT_LOOP;
+ ifp->if_snd.ifq_maxlen = ifqmaxlen;
+ ifp->if_hdrlen = PFLOG_HDRLEN;
+ if_attach(ifp);
+
+#if NBPFILTER > 0
+ bpfattach(&pflogif[i].sc_if.if_bpf, ifp, DLT_LOOP,
+ PFLOG_HDRLEN);
+#endif
+#ifdef INET6
+ nd6_ifattach(ifp);
+#endif
+ }
+}
+
+/*
+ * Start output on the pflog interface.
+ */
+void
+pflogstart(ifp)
+ struct ifnet *ifp;
+{
+ struct mbuf *m;
+ int s;
+
+ for (;;) {
+ s = splimp();
+ IF_DROP(&ifp->if_snd);
+ IF_DEQUEUE(&ifp->if_snd, m);
+ splx(s);
+
+ if (m == NULL)
+ return;
+ else
+ m_freem(m);
+ }
+}
+
+int
+pflogoutput(ifp, m, dst, rt)
+ struct ifnet *ifp;
+ register struct mbuf *m;
+ struct sockaddr *dst;
+ register struct rtentry *rt;
+{
+ m_freem(m);
+ return 0;
+}
+
+/* ARGSUSED */
+void
+pflogrtrequest(cmd, rt, sa)
+int cmd;
+struct rtentry *rt;
+struct sockaddr *sa;
+{
+ if (rt)
+ rt->rt_rmx.rmx_mtu = PFLOGMTU;
+}
+
+/* ARGSUSED */
+int
+pflogioctl(ifp, cmd, data)
+ register struct ifnet *ifp;
+ u_long cmd;
+ caddr_t data;
+{
+ switch (cmd) {
+ case SIOCSIFADDR:
+ case SIOCAIFADDR:
+ case SIOCSIFDSTADDR:
+ case SIOCSIFFLAGS:
+ if (ifp->if_flags & IFF_UP)
+ ifp->if_flags |= IFF_RUNNING;
+ else
+ ifp->if_flags &= ~IFF_RUNNING;
+ break;
+
+ default:
+ return EINVAL;
+ }
+
+ return (0);
+}
diff --git a/sys/net/if_pflog.h b/sys/net/if_pflog.h
new file mode 100644
index 00000000000..48cfd11a678
--- /dev/null
+++ b/sys/net/if_pflog.h
@@ -0,0 +1,50 @@
+/* $OpenBSD: if_pflog.h,v 1.1 2001/06/25 20:48:17 provos Exp $ */
+/*
+ * The authors of this code are John Ioannidis (ji@tla.org),
+ * Angelos D. Keromytis (kermit@csd.uch.gr) and
+ * Niels Provos (provos@physnet.uni-hamburg.de).
+ *
+ * This code was written by John Ioannidis for BSD/OS in Athens, Greece,
+ * in November 1995.
+ *
+ * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996,
+ * by Angelos D. Keromytis.
+ *
+ * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis
+ * and Niels Provos.
+ *
+ * Copyright (C) 1995, 1996, 1997, 1998 by John Ioannidis, Angelos D. Keromytis
+ * and Niels Provos.
+ * Copyright (c) 2001, Angelos D. Keromytis.
+ *
+ * Permission to use, copy, and modify this software with or without fee
+ * is hereby granted, provided that this entire notice is included in
+ * all copies of any software which is or includes a copy or
+ * modification of this software.
+ * You may use this code under the GNU public license if you so wish. Please
+ * contribute changes back to the authors under this freer than GPL license
+ * so that we may further the use of strong encryption without limitations to
+ * all.
+ *
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
+ * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
+ * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
+ * PURPOSE.
+ */
+
+#ifndef _NET_IF_PFLOG_H_
+#define _NET_IF_PFLOG_H_
+
+#define PFLOG_HDRLEN 4
+
+struct pflog_softc {
+ struct ifnet sc_if; /* the interface */
+};
+
+struct pfloghdr {
+ u_int32_t af;
+};
+
+extern struct pflog_softc pflogif[];
+#endif /* _NET_IF_ENC_H_ */
diff --git a/sys/net/pf.c b/sys/net/pf.c
index c871b1e74c2..f1090497452 100644
--- a/sys/net/pf.c
+++ b/sys/net/pf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf.c,v 1.35 2001/06/25 19:53:37 art Exp $ */
+/* $OpenBSD: pf.c,v 1.36 2001/06/25 20:48:17 provos Exp $ */
/*
* Copyright (c) 2001, Daniel Hartmeier
@@ -43,8 +43,10 @@
#include <net/if.h>
#include <net/if_types.h>
+#include <net/bpf.h>
#include <net/route.h>
#include <net/pfvar.h>
+#include <net/if_pflog.h>
#include <netinet/in.h>
#include <netinet/in_var.h>
@@ -54,6 +56,8 @@
#include <netinet/udp.h>
#include <netinet/ip_icmp.h>
+#include "bpfilter.h"
+
/*
* Tree data structure
*/
@@ -141,12 +145,12 @@ int match_addr(u_int8_t, u_int32_t, u_int32_t, u_int32_t);
int match_port(u_int8_t, u_int16_t, u_int16_t, u_int16_t);
struct pf_nat *get_nat(struct ifnet *, u_int8_t, u_int32_t);
struct pf_rdr *get_rdr(struct ifnet *, u_int8_t, u_int32_t, u_int16_t);
-int pf_test_tcp(int, struct ifnet *, int, struct ip *,
- struct tcphdr *);
-int pf_test_udp(int, struct ifnet *, int, struct ip *,
- struct udphdr *);
-int pf_test_icmp(int, struct ifnet *, int, struct ip *,
- struct icmp *);
+int pf_test_tcp(int, struct ifnet *, struct mbuf **, int,
+ struct ip *, struct tcphdr *);
+int pf_test_udp(int, struct ifnet *, struct mbuf **,
+ int, struct ip *, struct udphdr *);
+int pf_test_icmp(int, struct ifnet *, struct mbuf **,
+ int, struct ip *, struct icmp *);
struct pf_state *pf_test_state_tcp(int, struct ifnet *, struct mbuf **, int,
struct ip *, struct tcphdr *);
struct pf_state *pf_test_state_udp(int, struct ifnet *, struct mbuf **, int,
@@ -156,6 +160,16 @@ struct pf_state *pf_test_state_icmp(int, struct ifnet *, struct mbuf **, int,
void *pull_hdr(struct ifnet *, struct mbuf **, int, int, int,
struct ip *, int *);
int pf_test(int, struct ifnet *, struct mbuf **);
+int pflog_packet(struct mbuf *, int, int);
+
+#define PFLOG_PACKET(x,a,b,c) \
+ do { \
+ HTONS((x)->ip_len); \
+ HTONS((x)->ip_off); \
+ pflog_packet(a,b,c); \
+ NTOHS((x)->ip_len); \
+ NTOHS((x)->ip_off); \
+ } while (0)
int
tree_key_compare(struct pf_tree_key *a, struct pf_tree_key *b)
@@ -333,6 +347,39 @@ tree_remove(struct pf_tree_node **p, struct pf_tree_key *key)
return (deltaH);
}
+int
+pflog_packet(struct mbuf *m, int af, int action)
+{
+#if NBPFILTER > 0
+ struct ifnet *ifn;
+ struct pfloghdr hdr;
+ struct mbuf m1;
+
+ hdr.af = htonl(af);
+
+ m1.m_next = m;
+ m1.m_len = PFLOG_HDRLEN;
+ m1.m_data = (char *) &hdr;
+
+ switch (action) {
+ case PF_DROP_RST:
+ case PF_DROP:
+ ifn = &(pflogif[0].sc_if);
+ break;
+ case PF_PASS:
+ ifn = &(pflogif[1].sc_if);
+ break;
+ default:
+ return (-1);
+ }
+
+ if (ifn->if_bpf)
+ bpf_mtap(ifn->if_bpf, &m1);
+#endif
+
+ return (0);
+}
+
struct pf_state *
find_state(struct pf_tree_node *p, struct pf_tree_key *key)
{
@@ -1137,8 +1184,8 @@ get_rdr(struct ifnet *ifp, u_int8_t proto, u_int32_t addr, u_int16_t port)
}
int
-pf_test_tcp(int direction, struct ifnet *ifp, int off, struct ip *h,
- struct tcphdr *th)
+pf_test_tcp(int direction, struct ifnet *ifp, struct mbuf **m, int off,
+ struct ip *h, struct tcphdr *th)
{
struct pf_nat *nat = NULL;
struct pf_rdr *rdr = NULL;
@@ -1189,25 +1236,8 @@ pf_test_tcp(int direction, struct ifnet *ifp, int off, struct ip *h,
nr++;
}
- if ((rm != NULL) && rm->log) {
- u_int32_t seq = ntohl(th->th_seq);
- u_int16_t len = h->ip_len - off - (th->th_off << 2);
-
- printf("pf: @%u", mnr);
- printf(" %s %s", rm->action ? "block" : "pass",
- direction ? "out" : "in");
- printf(" on %s proto tcp", ifp->if_xname);
- printf(" from ");
- print_host(h->ip_src.s_addr, th->th_sport);
- printf(" to ");
- print_host(h->ip_dst.s_addr, th->th_dport);
- print_flags(th->th_flags);
- if (len || (th->th_flags & (TH_SYN | TH_FIN | TH_RST)))
- printf(" %lu:%lu(%u)", seq, seq + len, len);
- if (th->th_ack)
- printf(" ack=%lu", ntohl(th->th_ack));
- printf("\n");
- }
+ if ((rm != NULL) && rm->log)
+ PFLOG_PACKET(h, *m, AF_INET, rm->action);
if ((rm != NULL) && (rm->action == PF_DROP_RST)) {
/* undo NAT/RST changes, if they have taken place */
@@ -1281,8 +1311,8 @@ pf_test_tcp(int direction, struct ifnet *ifp, int off, struct ip *h,
}
int
-pf_test_udp(int direction, struct ifnet *ifp, int off, struct ip *h,
- struct udphdr *uh)
+pf_test_udp(int direction, struct ifnet *ifp, struct mbuf **m, int off,
+ struct ip *h, struct udphdr *uh)
{
struct pf_nat *nat = NULL;
struct pf_rdr *rdr = NULL;
@@ -1331,17 +1361,8 @@ pf_test_udp(int direction, struct ifnet *ifp, int off, struct ip *h,
nr++;
}
- if (rm != NULL && rm->log) {
- printf("pf: @%u", mnr);
- printf(" %s %s", rm->action ? "block" : "pass", direction ? "out" :
- "in");
- printf(" on %s proto udp", ifp->if_xname);
- printf(" from ");
- print_host(h->ip_src.s_addr, uh->uh_sport);
- printf(" to ");
- print_host(h->ip_dst.s_addr, uh->uh_dport);
- printf("\n");
- }
+ if (rm != NULL && rm->log)
+ PFLOG_PACKET(h, *m, AF_INET, rm->action);
if (rm != NULL && rm->action != PF_PASS)
return (PF_DROP);
@@ -1403,8 +1424,8 @@ pf_test_udp(int direction, struct ifnet *ifp, int off, struct ip *h,
}
int
-pf_test_icmp(int direction, struct ifnet *ifp, int off, struct ip *h,
- struct icmp *ih)
+pf_test_icmp(int direction, struct ifnet *ifp, struct mbuf **m, int off,
+ struct ip *h, struct icmp *ih)
{
struct pf_nat *nat = NULL;
u_int32_t baddr;
@@ -1438,18 +1459,8 @@ pf_test_icmp(int direction, struct ifnet *ifp, int off, struct ip *h,
nr++;
}
- if (rm != NULL && rm->log) {
- printf("pf: @%u", mnr);
- printf(" %s %s", rm->action ? "block" : "pass", direction ? "in" :
- "out");
- printf(" on %s proto icmp", ifp->if_xname);
- printf(" from ");
- print_host(h->ip_src.s_addr, 0);
- printf(" to ");
- print_host(h->ip_dst.s_addr, 0);
- printf(" type %u/%u", ih->icmp_type, ih->icmp_code);
- printf("\n");
- }
+ if (rm != NULL && rm->log)
+ PFLOG_PACKET(h, *m, AF_INET, rm->action);
if (rm != NULL && rm->action != PF_PASS)
return (PF_DROP);
@@ -1934,7 +1945,7 @@ pf_test(int direction, struct ifnet *ifp, struct mbuf **m)
if (pf_test_state_tcp(direction, ifp, m, off, h, th))
action = PF_PASS;
else
- action = pf_test_tcp(direction, ifp, off, h, th);
+ action = pf_test_tcp(direction, ifp, m, off, h, th);
break;
}
@@ -1947,7 +1958,7 @@ pf_test(int direction, struct ifnet *ifp, struct mbuf **m)
if (pf_test_state_udp(direction, ifp, m, off, h, uh))
action = PF_PASS;
else
- action = pf_test_udp(direction, ifp, off, h, uh);
+ action = pf_test_udp(direction, ifp, m, off, h, uh);
break;
}
@@ -1960,7 +1971,7 @@ pf_test(int direction, struct ifnet *ifp, struct mbuf **m)
if (pf_test_state_icmp(direction, ifp, m, off, h, ih))
action = PF_PASS;
else
- action = pf_test_icmp(direction, ifp, off, h, ih);
+ action = pf_test_icmp(direction, ifp, m, off, h, ih);
break;
}