diff options
author | Niels Provos <provos@cvs.openbsd.org> | 2001-06-25 20:48:18 +0000 |
---|---|---|
committer | Niels Provos <provos@cvs.openbsd.org> | 2001-06-25 20:48:18 +0000 |
commit | d7aea208023a136429b6e7996563c4a0886f4620 (patch) | |
tree | b49bb4ac7452af270cc3f83dfcaabafedd98ed34 /sys | |
parent | ff92ff78ad1439a28f881d242014ee4b153e4bd3 (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/GENERIC | 3 | ||||
-rw-r--r-- | sys/conf/files | 4 | ||||
-rw-r--r-- | sys/net/if_pflog.c | 198 | ||||
-rw-r--r-- | sys/net/if_pflog.h | 50 | ||||
-rw-r--r-- | sys/net/pf.c | 127 |
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; } |